1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2017-2019 Mellanox Technologies. All rights reserved */
4 #define pr_fmt(fmt) "mlxfw: " fmt
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/delay.h>
11 #include "mlxfw_mfa2.h"
13 #define MLXFW_FSM_STATE_WAIT_CYCLE_MS 200
14 #define MLXFW_FSM_STATE_WAIT_TIMEOUT_MS 30000
15 #define MLXFW_FSM_STATE_WAIT_ROUNDS \
16 (MLXFW_FSM_STATE_WAIT_TIMEOUT_MS / MLXFW_FSM_STATE_WAIT_CYCLE_MS)
17 #define MLXFW_FSM_MAX_COMPONENT_SIZE (10 * (1 << 20))
19 static const int mlxfw_fsm_state_errno[] = {
20 [MLXFW_FSM_STATE_ERR_ERROR] = -EIO,
21 [MLXFW_FSM_STATE_ERR_REJECTED_DIGEST_ERR] = -EBADMSG,
22 [MLXFW_FSM_STATE_ERR_REJECTED_NOT_APPLICABLE] = -ENOENT,
23 [MLXFW_FSM_STATE_ERR_REJECTED_UNKNOWN_KEY] = -ENOKEY,
24 [MLXFW_FSM_STATE_ERR_REJECTED_AUTH_FAILED] = -EACCES,
25 [MLXFW_FSM_STATE_ERR_REJECTED_UNSIGNED] = -EKEYREVOKED,
26 [MLXFW_FSM_STATE_ERR_REJECTED_KEY_NOT_APPLICABLE] = -EKEYREJECTED,
27 [MLXFW_FSM_STATE_ERR_REJECTED_BAD_FORMAT] = -ENOEXEC,
28 [MLXFW_FSM_STATE_ERR_BLOCKED_PENDING_RESET] = -EBUSY,
29 [MLXFW_FSM_STATE_ERR_MAX] = -EINVAL
32 #define MLXFW_ERR_PRFX "Firmware flash failed: "
33 #define MLXFW_ERR_MSG(fwdev, extack, msg, err) do { \
34 mlxfw_err(fwdev, "%s, err (%d)\n", MLXFW_ERR_PRFX msg, err); \
35 NL_SET_ERR_MSG_MOD(extack, MLXFW_ERR_PRFX msg); \
38 static int mlxfw_fsm_state_err(struct mlxfw_dev *mlxfw_dev,
39 struct netlink_ext_ack *extack,
40 enum mlxfw_fsm_state_err err)
42 enum mlxfw_fsm_state_err fsm_state_err;
44 fsm_state_err = min_t(enum mlxfw_fsm_state_err, err,
45 MLXFW_FSM_STATE_ERR_MAX);
47 switch (fsm_state_err) {
48 case MLXFW_FSM_STATE_ERR_ERROR:
49 MLXFW_ERR_MSG(mlxfw_dev, extack, "general error", err);
51 case MLXFW_FSM_STATE_ERR_REJECTED_DIGEST_ERR:
52 MLXFW_ERR_MSG(mlxfw_dev, extack, "component hash mismatch", err);
54 case MLXFW_FSM_STATE_ERR_REJECTED_NOT_APPLICABLE:
55 MLXFW_ERR_MSG(mlxfw_dev, extack, "component not applicable", err);
57 case MLXFW_FSM_STATE_ERR_REJECTED_UNKNOWN_KEY:
58 MLXFW_ERR_MSG(mlxfw_dev, extack, "unknown key", err);
60 case MLXFW_FSM_STATE_ERR_REJECTED_AUTH_FAILED:
61 MLXFW_ERR_MSG(mlxfw_dev, extack, "authentication failed", err);
63 case MLXFW_FSM_STATE_ERR_REJECTED_UNSIGNED:
64 MLXFW_ERR_MSG(mlxfw_dev, extack, "component was not signed", err);
66 case MLXFW_FSM_STATE_ERR_REJECTED_KEY_NOT_APPLICABLE:
67 MLXFW_ERR_MSG(mlxfw_dev, extack, "key not applicable", err);
69 case MLXFW_FSM_STATE_ERR_REJECTED_BAD_FORMAT:
70 MLXFW_ERR_MSG(mlxfw_dev, extack, "bad format", err);
72 case MLXFW_FSM_STATE_ERR_BLOCKED_PENDING_RESET:
73 MLXFW_ERR_MSG(mlxfw_dev, extack, "pending reset", err);
75 case MLXFW_FSM_STATE_ERR_OK:
76 case MLXFW_FSM_STATE_ERR_MAX:
77 MLXFW_ERR_MSG(mlxfw_dev, extack, "unknown error", err);
81 return mlxfw_fsm_state_errno[fsm_state_err];
84 static int mlxfw_fsm_state_wait(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
85 enum mlxfw_fsm_state fsm_state,
86 struct netlink_ext_ack *extack)
88 enum mlxfw_fsm_state_err fsm_state_err;
89 enum mlxfw_fsm_state curr_fsm_state;
93 times = MLXFW_FSM_STATE_WAIT_ROUNDS;
95 err = mlxfw_dev->ops->fsm_query_state(mlxfw_dev, fwhandle,
96 &curr_fsm_state, &fsm_state_err);
98 MLXFW_ERR_MSG(mlxfw_dev, extack, "FSM state query failed", err);
102 if (fsm_state_err != MLXFW_FSM_STATE_ERR_OK)
103 return mlxfw_fsm_state_err(mlxfw_dev, extack, fsm_state_err);
105 if (curr_fsm_state != fsm_state) {
107 MLXFW_ERR_MSG(mlxfw_dev, extack,
108 "Timeout reached on FSM state change", -ETIMEDOUT);
111 msleep(MLXFW_FSM_STATE_WAIT_CYCLE_MS);
118 mlxfw_fsm_reactivate_err(struct mlxfw_dev *mlxfw_dev,
119 struct netlink_ext_ack *extack, u8 err)
121 enum mlxfw_fsm_reactivate_status status;
123 #define MXFW_REACT_PRFX "Reactivate FSM: "
124 #define MLXFW_REACT_ERR(msg, err) \
125 MLXFW_ERR_MSG(mlxfw_dev, extack, MXFW_REACT_PRFX msg, err)
127 status = min_t(enum mlxfw_fsm_reactivate_status, err,
128 MLXFW_FSM_REACTIVATE_STATUS_MAX);
131 case MLXFW_FSM_REACTIVATE_STATUS_BUSY:
132 MLXFW_REACT_ERR("busy", err);
134 case MLXFW_FSM_REACTIVATE_STATUS_PROHIBITED_FW_VER_ERR:
135 MLXFW_REACT_ERR("prohibited fw ver", err);
137 case MLXFW_FSM_REACTIVATE_STATUS_FIRST_PAGE_COPY_FAILED:
138 MLXFW_REACT_ERR("first page copy failed", err);
140 case MLXFW_FSM_REACTIVATE_STATUS_FIRST_PAGE_ERASE_FAILED:
141 MLXFW_REACT_ERR("first page erase failed", err);
143 case MLXFW_FSM_REACTIVATE_STATUS_FIRST_PAGE_RESTORE_FAILED:
144 MLXFW_REACT_ERR("first page restore failed", err);
146 case MLXFW_FSM_REACTIVATE_STATUS_CANDIDATE_FW_DEACTIVATION_FAILED:
147 MLXFW_REACT_ERR("candidate fw deactivation failed", err);
149 case MLXFW_FSM_REACTIVATE_STATUS_ERR_DEVICE_RESET_REQUIRED:
150 MLXFW_REACT_ERR("device reset required", err);
152 case MLXFW_FSM_REACTIVATE_STATUS_ERR_FW_PROGRAMMING_NEEDED:
153 MLXFW_REACT_ERR("fw programming needed", err);
155 case MLXFW_FSM_REACTIVATE_STATUS_FW_ALREADY_ACTIVATED:
156 MLXFW_REACT_ERR("fw already activated", err);
158 case MLXFW_FSM_REACTIVATE_STATUS_OK:
159 case MLXFW_FSM_REACTIVATE_STATUS_MAX:
160 MLXFW_REACT_ERR("unexpected error", err);
166 static int mlxfw_fsm_reactivate(struct mlxfw_dev *mlxfw_dev,
167 struct netlink_ext_ack *extack,
173 if (!mlxfw_dev->ops->fsm_reactivate)
176 err = mlxfw_dev->ops->fsm_reactivate(mlxfw_dev, &status);
177 if (err == -EOPNOTSUPP) {
183 MLXFW_ERR_MSG(mlxfw_dev, extack,
184 "Could not reactivate firmware flash", err);
188 if (status == MLXFW_FSM_REACTIVATE_STATUS_OK ||
189 status == MLXFW_FSM_REACTIVATE_STATUS_FW_ALREADY_ACTIVATED)
192 return mlxfw_fsm_reactivate_err(mlxfw_dev, extack, status);
195 static void mlxfw_status_notify(struct mlxfw_dev *mlxfw_dev,
196 const char *msg, const char *comp_name,
197 u32 done_bytes, u32 total_bytes)
199 devlink_flash_update_status_notify(mlxfw_dev->devlink, msg, comp_name,
200 done_bytes, total_bytes);
203 #define MLXFW_ALIGN_DOWN(x, align_bits) ((x) & ~((1 << (align_bits)) - 1))
204 #define MLXFW_ALIGN_UP(x, align_bits) \
205 MLXFW_ALIGN_DOWN((x) + ((1 << (align_bits)) - 1), (align_bits))
207 static int mlxfw_flash_component(struct mlxfw_dev *mlxfw_dev,
209 struct mlxfw_mfa2_component *comp,
210 bool reactivate_supp,
211 struct netlink_ext_ack *extack)
213 u16 comp_max_write_size;
222 sprintf(comp_name, "%u", comp->index);
224 err = mlxfw_dev->ops->component_query(mlxfw_dev, comp->index,
225 &comp_max_size, &comp_align_bits,
226 &comp_max_write_size);
228 MLXFW_ERR_MSG(mlxfw_dev, extack, "FSM component query failed", err);
232 comp_max_size = min_t(u32, comp_max_size, MLXFW_FSM_MAX_COMPONENT_SIZE);
233 if (comp->data_size > comp_max_size) {
234 MLXFW_ERR_MSG(mlxfw_dev, extack,
235 "Component size is bigger than limit", -EINVAL);
239 comp_max_write_size = MLXFW_ALIGN_DOWN(comp_max_write_size,
242 mlxfw_dbg(mlxfw_dev, "Component update\n");
243 mlxfw_status_notify(mlxfw_dev, "Updating component", comp_name, 0, 0);
244 err = mlxfw_dev->ops->fsm_component_update(mlxfw_dev, fwhandle,
248 if (!reactivate_supp)
249 MLXFW_ERR_MSG(mlxfw_dev, extack,
250 "FSM component update failed, FW reactivate is not supported",
253 MLXFW_ERR_MSG(mlxfw_dev, extack,
254 "FSM component update failed", err);
258 err = mlxfw_fsm_state_wait(mlxfw_dev, fwhandle,
259 MLXFW_FSM_STATE_DOWNLOAD, extack);
263 mlxfw_dbg(mlxfw_dev, "Component download\n");
264 mlxfw_status_notify(mlxfw_dev, "Downloading component",
265 comp_name, 0, comp->data_size);
267 offset < MLXFW_ALIGN_UP(comp->data_size, comp_align_bits);
268 offset += comp_max_write_size) {
269 block_ptr = comp->data + offset;
270 block_size = (u16) min_t(u32, comp->data_size - offset,
271 comp_max_write_size);
272 err = mlxfw_dev->ops->fsm_block_download(mlxfw_dev, fwhandle,
273 block_ptr, block_size,
276 MLXFW_ERR_MSG(mlxfw_dev, extack,
277 "Component download failed", err);
280 mlxfw_status_notify(mlxfw_dev, "Downloading component",
281 comp_name, offset + block_size,
285 mlxfw_dbg(mlxfw_dev, "Component verify\n");
286 mlxfw_status_notify(mlxfw_dev, "Verifying component", comp_name, 0, 0);
287 err = mlxfw_dev->ops->fsm_component_verify(mlxfw_dev, fwhandle,
290 MLXFW_ERR_MSG(mlxfw_dev, extack,
291 "FSM component verify failed", err);
295 err = mlxfw_fsm_state_wait(mlxfw_dev, fwhandle,
296 MLXFW_FSM_STATE_LOCKED, extack);
302 mlxfw_dev->ops->fsm_cancel(mlxfw_dev, fwhandle);
306 static int mlxfw_flash_components(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
307 struct mlxfw_mfa2_file *mfa2_file,
308 bool reactivate_supp,
309 struct netlink_ext_ack *extack)
315 err = mlxfw_mfa2_file_component_count(mfa2_file, mlxfw_dev->psid,
316 mlxfw_dev->psid_size,
319 MLXFW_ERR_MSG(mlxfw_dev, extack,
320 "Could not find device PSID in MFA2 file", err);
324 for (i = 0; i < component_count; i++) {
325 struct mlxfw_mfa2_component *comp;
327 comp = mlxfw_mfa2_file_component_get(mfa2_file, mlxfw_dev->psid,
328 mlxfw_dev->psid_size, i);
331 MLXFW_ERR_MSG(mlxfw_dev, extack,
332 "Failed to get MFA2 component", err);
336 mlxfw_info(mlxfw_dev, "Flashing component type %d\n",
338 err = mlxfw_flash_component(mlxfw_dev, fwhandle, comp,
339 reactivate_supp, extack);
340 mlxfw_mfa2_file_component_put(comp);
347 int mlxfw_firmware_flash(struct mlxfw_dev *mlxfw_dev,
348 const struct firmware *firmware,
349 struct netlink_ext_ack *extack)
351 struct mlxfw_mfa2_file *mfa2_file;
352 bool reactivate_supp = true;
356 if (!mlxfw_mfa2_check(firmware)) {
357 MLXFW_ERR_MSG(mlxfw_dev, extack,
358 "Firmware file is not MFA2", -EINVAL);
362 mfa2_file = mlxfw_mfa2_file_init(firmware);
363 if (IS_ERR(mfa2_file)) {
364 err = PTR_ERR(mfa2_file);
365 MLXFW_ERR_MSG(mlxfw_dev, extack,
366 "Failed to initialize MFA2 firmware file", err);
370 mlxfw_info(mlxfw_dev, "Initialize firmware flash process\n");
371 devlink_flash_update_begin_notify(mlxfw_dev->devlink);
372 mlxfw_status_notify(mlxfw_dev, "Initializing firmware flash process",
374 err = mlxfw_dev->ops->fsm_lock(mlxfw_dev, &fwhandle);
376 MLXFW_ERR_MSG(mlxfw_dev, extack,
377 "Could not lock the firmware FSM", err);
381 err = mlxfw_fsm_state_wait(mlxfw_dev, fwhandle,
382 MLXFW_FSM_STATE_LOCKED, extack);
384 goto err_state_wait_idle_to_locked;
386 err = mlxfw_fsm_reactivate(mlxfw_dev, extack, &reactivate_supp);
388 goto err_fsm_reactivate;
390 err = mlxfw_fsm_state_wait(mlxfw_dev, fwhandle,
391 MLXFW_FSM_STATE_LOCKED, extack);
393 goto err_state_wait_reactivate_to_locked;
395 err = mlxfw_flash_components(mlxfw_dev, fwhandle, mfa2_file,
396 reactivate_supp, extack);
398 goto err_flash_components;
400 mlxfw_dbg(mlxfw_dev, "Activate image\n");
401 mlxfw_status_notify(mlxfw_dev, "Activating image", NULL, 0, 0);
402 err = mlxfw_dev->ops->fsm_activate(mlxfw_dev, fwhandle);
404 MLXFW_ERR_MSG(mlxfw_dev, extack,
405 "Could not activate the downloaded image", err);
406 goto err_fsm_activate;
409 err = mlxfw_fsm_state_wait(mlxfw_dev, fwhandle,
410 MLXFW_FSM_STATE_LOCKED, extack);
412 goto err_state_wait_activate_to_locked;
414 mlxfw_dbg(mlxfw_dev, "Handle release\n");
415 mlxfw_dev->ops->fsm_release(mlxfw_dev, fwhandle);
417 mlxfw_info(mlxfw_dev, "Firmware flash done\n");
418 mlxfw_status_notify(mlxfw_dev, "Firmware flash done", NULL, 0, 0);
419 mlxfw_mfa2_file_fini(mfa2_file);
420 devlink_flash_update_end_notify(mlxfw_dev->devlink);
423 err_state_wait_activate_to_locked:
425 err_flash_components:
426 err_state_wait_reactivate_to_locked:
428 err_state_wait_idle_to_locked:
429 mlxfw_dev->ops->fsm_release(mlxfw_dev, fwhandle);
431 mlxfw_mfa2_file_fini(mfa2_file);
432 devlink_flash_update_end_notify(mlxfw_dev->devlink);
435 EXPORT_SYMBOL(mlxfw_firmware_flash);
437 MODULE_LICENSE("Dual BSD/GPL");
438 MODULE_AUTHOR("Yotam Gigi <yotamg@mellanox.com>");
439 MODULE_DESCRIPTION("Mellanox firmware flash lib");