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/mlxfw/mlxfw_fsm.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-3-Clause
    3  *
    4  * Copyright (c) 2017-2019 Mellanox Technologies.
    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
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of Mellanox nor the names of contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  * $FreeBSD$
   32  */
   33 
   34 #define pr_fmt(fmt) "mlxfw: " fmt
   35 
   36 #include <linux/kernel.h>
   37 #include <linux/module.h>
   38 #include <linux/delay.h>
   39 
   40 #include "mlxfw.h"
   41 #include "mlxfw_mfa2.h"
   42 
   43 #define MLXFW_FSM_STATE_WAIT_CYCLE_MS 200
   44 #define MLXFW_FSM_STATE_WAIT_TIMEOUT_MS 30000
   45 #define MLXFW_FSM_STATE_WAIT_ROUNDS \
   46         (MLXFW_FSM_STATE_WAIT_TIMEOUT_MS / MLXFW_FSM_STATE_WAIT_CYCLE_MS)
   47 #define MLXFW_FSM_MAX_COMPONENT_SIZE (10 * (1 << 20))
   48 
   49 static const char * const mlxfw_fsm_state_err_str[] = {
   50         [MLXFW_FSM_STATE_ERR_ERROR] =
   51                 "general error",
   52         [MLXFW_FSM_STATE_ERR_REJECTED_DIGEST_ERR] =
   53                 "component hash mismatch",
   54         [MLXFW_FSM_STATE_ERR_REJECTED_NOT_APPLICABLE] =
   55                 "component not applicable",
   56         [MLXFW_FSM_STATE_ERR_REJECTED_UNKNOWN_KEY] =
   57                 "unknown key",
   58         [MLXFW_FSM_STATE_ERR_REJECTED_AUTH_FAILED] =
   59                 "authentication failed",
   60         [MLXFW_FSM_STATE_ERR_REJECTED_UNSIGNED] =
   61                 "component was not signed",
   62         [MLXFW_FSM_STATE_ERR_REJECTED_KEY_NOT_APPLICABLE] =
   63                 "key not applicable",
   64         [MLXFW_FSM_STATE_ERR_REJECTED_BAD_FORMAT] =
   65                 "bad format",
   66         [MLXFW_FSM_STATE_ERR_BLOCKED_PENDING_RESET] =
   67                 "pending reset",
   68         [MLXFW_FSM_STATE_ERR_MAX] =
   69                 "unknown error"
   70 };
   71 
   72 static int mlxfw_fsm_state_wait(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
   73                                 enum mlxfw_fsm_state fsm_state)
   74 {
   75         enum mlxfw_fsm_state_err fsm_state_err;
   76         enum mlxfw_fsm_state curr_fsm_state;
   77         int times;
   78         int err;
   79 
   80         times = MLXFW_FSM_STATE_WAIT_ROUNDS;
   81 retry:
   82         err = mlxfw_dev->ops->fsm_query_state(mlxfw_dev, fwhandle,
   83                                               &curr_fsm_state, &fsm_state_err);
   84         if (err)
   85                 return err;
   86 
   87         if (fsm_state_err != MLXFW_FSM_STATE_ERR_OK) {
   88                 pr_err("Firmware flash failed: %s\n",
   89                        mlxfw_fsm_state_err_str[fsm_state_err]);
   90                 return -EINVAL;
   91         }
   92         if (curr_fsm_state != fsm_state) {
   93                 if (--times == 0) {
   94                         pr_err("Timeout reached on FSM state change");
   95                         return -ETIMEDOUT;
   96                 }
   97                 msleep(MLXFW_FSM_STATE_WAIT_CYCLE_MS);
   98                 goto retry;
   99         }
  100         return 0;
  101 }
  102 
  103 #define MLXFW_ALIGN_DOWN(x, align_bits) ((x) & ~((1 << (align_bits)) - 1))
  104 #define MLXFW_ALIGN_UP(x, align_bits) \
  105                 MLXFW_ALIGN_DOWN((x) + ((1 << (align_bits)) - 1), (align_bits))
  106 
  107 static int mlxfw_flash_component(struct mlxfw_dev *mlxfw_dev,
  108                                  u32 fwhandle,
  109                                  struct mlxfw_mfa2_component *comp)
  110 {
  111         u16 comp_max_write_size;
  112         u8 comp_align_bits;
  113         u32 comp_max_size;
  114         u16 block_size;
  115         u8 *block_ptr;
  116         u32 offset;
  117         int err;
  118 
  119         err = mlxfw_dev->ops->component_query(mlxfw_dev, comp->index,
  120                                               &comp_max_size, &comp_align_bits,
  121                                               &comp_max_write_size);
  122         if (err)
  123                 return err;
  124 
  125         comp_max_size = min_t(u32, comp_max_size, MLXFW_FSM_MAX_COMPONENT_SIZE);
  126         if (comp->data_size > comp_max_size) {
  127                 pr_err("Component %d is of size %d which is bigger than limit %d\n",
  128                        comp->index, comp->data_size, comp_max_size);
  129                 return -EINVAL;
  130         }
  131 
  132         comp_max_write_size = MLXFW_ALIGN_DOWN(comp_max_write_size,
  133                                                comp_align_bits);
  134 
  135         pr_debug("Component update\n");
  136         err = mlxfw_dev->ops->fsm_component_update(mlxfw_dev, fwhandle,
  137                                                    comp->index,
  138                                                    comp->data_size);
  139         if (err)
  140                 return err;
  141 
  142         err = mlxfw_fsm_state_wait(mlxfw_dev, fwhandle,
  143                                    MLXFW_FSM_STATE_DOWNLOAD);
  144         if (err)
  145                 goto err_out;
  146 
  147         pr_debug("Component download\n");
  148         for (offset = 0;
  149              offset < MLXFW_ALIGN_UP(comp->data_size, comp_align_bits);
  150              offset += comp_max_write_size) {
  151                 block_ptr = comp->data + offset;
  152                 block_size = (u16) min_t(u32, comp->data_size - offset,
  153                                          comp_max_write_size);
  154                 err = mlxfw_dev->ops->fsm_block_download(mlxfw_dev, fwhandle,
  155                                                          block_ptr, block_size,
  156                                                          offset);
  157                 if (err)
  158                         goto err_out;
  159         }
  160 
  161         pr_debug("Component verify\n");
  162         err = mlxfw_dev->ops->fsm_component_verify(mlxfw_dev, fwhandle,
  163                                                    comp->index);
  164         if (err)
  165                 goto err_out;
  166 
  167         err = mlxfw_fsm_state_wait(mlxfw_dev, fwhandle, MLXFW_FSM_STATE_LOCKED);
  168         if (err)
  169                 goto err_out;
  170         return 0;
  171 
  172 err_out:
  173         mlxfw_dev->ops->fsm_cancel(mlxfw_dev, fwhandle);
  174         return err;
  175 }
  176 
  177 static int mlxfw_flash_components(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
  178                                   struct mlxfw_mfa2_file *mfa2_file)
  179 {
  180         u32 component_count;
  181         int err;
  182         int i;
  183 
  184         err = mlxfw_mfa2_file_component_count(mfa2_file, mlxfw_dev->psid,
  185                                               mlxfw_dev->psid_size,
  186                                               &component_count);
  187         if (err) {
  188                 pr_err("Could not find device PSID in MFA2 file\n");
  189                 return err;
  190         }
  191 
  192         for (i = 0; i < component_count; i++) {
  193                 struct mlxfw_mfa2_component *comp;
  194 
  195                 comp = mlxfw_mfa2_file_component_get(mfa2_file, mlxfw_dev->psid,
  196                                                      mlxfw_dev->psid_size, i);
  197                 if (IS_ERR(comp))
  198                         return PTR_ERR(comp);
  199 
  200                 pr_info("Flashing component type %d\n", comp->index);
  201                 err = mlxfw_flash_component(mlxfw_dev, fwhandle, comp);
  202                 mlxfw_mfa2_file_component_put(comp);
  203                 if (err)
  204                         return err;
  205         }
  206         return 0;
  207 }
  208 
  209 int mlxfw_firmware_flash(struct mlxfw_dev *mlxfw_dev,
  210                          const struct firmware *firmware)
  211 {
  212         struct mlxfw_mfa2_file *mfa2_file;
  213         u32 fwhandle;
  214         int err;
  215 
  216         if (!mlxfw_mfa2_check(firmware)) {
  217                 pr_err("Firmware file is not MFA2\n");
  218                 return -EINVAL;
  219         }
  220 
  221         mfa2_file = mlxfw_mfa2_file_init(firmware);
  222         if (IS_ERR(mfa2_file))
  223                 return PTR_ERR(mfa2_file);
  224 
  225         pr_info("Initialize firmware flash process\n");
  226         err = mlxfw_dev->ops->fsm_lock(mlxfw_dev, &fwhandle);
  227         if (err) {
  228                 pr_err("Could not lock the firmware FSM\n");
  229                 goto err_fsm_lock;
  230         }
  231 
  232         err = mlxfw_fsm_state_wait(mlxfw_dev, fwhandle,
  233                                    MLXFW_FSM_STATE_LOCKED);
  234         if (err)
  235                 goto err_state_wait_idle_to_locked;
  236 
  237         err = mlxfw_flash_components(mlxfw_dev, fwhandle, mfa2_file);
  238         if (err)
  239                 goto err_flash_components;
  240 
  241         pr_debug("Activate image\n");
  242         err = mlxfw_dev->ops->fsm_activate(mlxfw_dev, fwhandle);
  243         if (err) {
  244                 pr_err("Could not activate the downloaded image\n");
  245                 goto err_fsm_activate;
  246         }
  247 
  248         err = mlxfw_fsm_state_wait(mlxfw_dev, fwhandle, MLXFW_FSM_STATE_LOCKED);
  249         if (err)
  250                 goto err_state_wait_activate_to_locked;
  251 
  252         pr_debug("Handle release\n");
  253         mlxfw_dev->ops->fsm_release(mlxfw_dev, fwhandle);
  254 
  255         pr_info("Firmware flash done.\n");
  256         mlxfw_mfa2_file_fini(mfa2_file);
  257         return 0;
  258 
  259 err_state_wait_activate_to_locked:
  260 err_fsm_activate:
  261 err_flash_components:
  262 err_state_wait_idle_to_locked:
  263         mlxfw_dev->ops->fsm_release(mlxfw_dev, fwhandle);
  264 err_fsm_lock:
  265         mlxfw_mfa2_file_fini(mfa2_file);
  266         return err;
  267 }
  268 EXPORT_SYMBOL(mlxfw_firmware_flash);
  269 
  270 MODULE_LICENSE("Dual BSD/GPL");
  271 MODULE_AUTHOR("Yotam Gigi <yotamg@mellanox.com>");
  272 MODULE_DESCRIPTION("Mellanox firmware flash lib");
  273 MODULE_VERSION(mlxfw, 1);
  274 MODULE_DEPEND(mlxfw, linuxkpi, 1, 1, 1);
  275 MODULE_DEPEND(mlxfw, xz, 1, 1, 1);

Cache object: 3ebfaee5d2f701829a4837a40486479c


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