1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright (C) 2018-2019, Intel Corporation. */ |
3 | |
4 | #include <asm/unaligned.h> |
5 | #include <linux/uuid.h> |
6 | #include <linux/crc32.h> |
7 | #include <linux/pldmfw.h> |
8 | #include "ice.h" |
9 | #include "ice_fw_update.h" |
10 | |
11 | struct ice_fwu_priv { |
12 | struct pldmfw context; |
13 | |
14 | struct ice_pf *pf; |
15 | struct netlink_ext_ack *extack; |
16 | |
17 | /* Track which NVM banks to activate at the end of the update */ |
18 | u8 activate_flags; |
19 | |
20 | /* Track the firmware response of the required reset to complete the |
21 | * flash update. |
22 | * |
23 | * 0 - ICE_AQC_NVM_POR_FLAG - A full power on is required |
24 | * 1 - ICE_AQC_NVM_PERST_FLAG - A cold PCIe reset is required |
25 | * 2 - ICE_AQC_NVM_EMPR_FLAG - An EMP reset is required |
26 | */ |
27 | u8 reset_level; |
28 | |
29 | /* Track if EMP reset is available */ |
30 | u8 emp_reset_available; |
31 | }; |
32 | |
33 | /** |
34 | * ice_send_package_data - Send record package data to firmware |
35 | * @context: PLDM fw update structure |
36 | * @data: pointer to the package data |
37 | * @length: length of the package data |
38 | * |
39 | * Send a copy of the package data associated with the PLDM record matching |
40 | * this device to the firmware. |
41 | * |
42 | * Note that this function sends an AdminQ command that will fail unless the |
43 | * NVM resource has been acquired. |
44 | * |
45 | * Returns: zero on success, or a negative error code on failure. |
46 | */ |
47 | static int |
48 | ice_send_package_data(struct pldmfw *context, const u8 *data, u16 length) |
49 | { |
50 | struct ice_fwu_priv *priv = container_of(context, struct ice_fwu_priv, context); |
51 | struct netlink_ext_ack *extack = priv->extack; |
52 | struct device *dev = context->dev; |
53 | struct ice_pf *pf = priv->pf; |
54 | struct ice_hw *hw = &pf->hw; |
55 | u8 *package_data; |
56 | int status; |
57 | |
58 | dev_dbg(dev, "Sending PLDM record package data to firmware\n" ); |
59 | |
60 | package_data = kmemdup(p: data, size: length, GFP_KERNEL); |
61 | if (!package_data) |
62 | return -ENOMEM; |
63 | |
64 | status = ice_nvm_set_pkg_data(hw, del_pkg_data_flag: false, data: package_data, length, NULL); |
65 | |
66 | kfree(objp: package_data); |
67 | |
68 | if (status) { |
69 | dev_err(dev, "Failed to send record package data to firmware, err %d aq_err %s\n" , |
70 | status, ice_aq_str(hw->adminq.sq_last_status)); |
71 | NL_SET_ERR_MSG_MOD(extack, "Failed to record package data to firmware" ); |
72 | return -EIO; |
73 | } |
74 | |
75 | return 0; |
76 | } |
77 | |
78 | /** |
79 | * ice_check_component_response - Report firmware response to a component |
80 | * @pf: device private data structure |
81 | * @id: component id being checked |
82 | * @response: indicates whether this component can be updated |
83 | * @code: code indicating reason for response |
84 | * @extack: netlink extended ACK structure |
85 | * |
86 | * Check whether firmware indicates if this component can be updated. Report |
87 | * a suitable error message over the netlink extended ACK if the component |
88 | * cannot be updated. |
89 | * |
90 | * Returns: zero if the component can be updated, or -ECANCELED of the |
91 | * firmware indicates the component cannot be updated. |
92 | */ |
93 | static int |
94 | ice_check_component_response(struct ice_pf *pf, u16 id, u8 response, u8 code, |
95 | struct netlink_ext_ack *extack) |
96 | { |
97 | struct device *dev = ice_pf_to_dev(pf); |
98 | const char *component; |
99 | |
100 | switch (id) { |
101 | case NVM_COMP_ID_OROM: |
102 | component = "fw.undi" ; |
103 | break; |
104 | case NVM_COMP_ID_NVM: |
105 | component = "fw.mgmt" ; |
106 | break; |
107 | case NVM_COMP_ID_NETLIST: |
108 | component = "fw.netlist" ; |
109 | break; |
110 | default: |
111 | WARN(1, "Unexpected unknown component identifier 0x%02x" , id); |
112 | return -EINVAL; |
113 | } |
114 | |
115 | dev_dbg(dev, "%s: firmware response 0x%x, code 0x%x\n" , |
116 | component, response, code); |
117 | |
118 | switch (response) { |
119 | case ICE_AQ_NVM_PASS_COMP_CAN_BE_UPDATED: |
120 | /* firmware indicated this update is good to proceed */ |
121 | return 0; |
122 | case ICE_AQ_NVM_PASS_COMP_CAN_MAY_BE_UPDATEABLE: |
123 | dev_warn(dev, "firmware recommends not updating %s, as it may result in a downgrade. continuing anyways\n" , component); |
124 | return 0; |
125 | case ICE_AQ_NVM_PASS_COMP_CAN_NOT_BE_UPDATED: |
126 | dev_info(dev, "firmware has rejected updating %s\n" , component); |
127 | break; |
128 | } |
129 | |
130 | switch (code) { |
131 | case ICE_AQ_NVM_PASS_COMP_STAMP_IDENTICAL_CODE: |
132 | dev_err(dev, "Component comparison stamp for %s is identical to the running image\n" , |
133 | component); |
134 | NL_SET_ERR_MSG_MOD(extack, "Component comparison stamp is identical to running image" ); |
135 | break; |
136 | case ICE_AQ_NVM_PASS_COMP_STAMP_LOWER: |
137 | dev_err(dev, "Component comparison stamp for %s is lower than the running image\n" , |
138 | component); |
139 | NL_SET_ERR_MSG_MOD(extack, "Component comparison stamp is lower than running image" ); |
140 | break; |
141 | case ICE_AQ_NVM_PASS_COMP_INVALID_STAMP_CODE: |
142 | dev_err(dev, "Component comparison stamp for %s is invalid\n" , |
143 | component); |
144 | NL_SET_ERR_MSG_MOD(extack, "Component comparison stamp is invalid" ); |
145 | break; |
146 | case ICE_AQ_NVM_PASS_COMP_CONFLICT_CODE: |
147 | dev_err(dev, "%s conflicts with a previous component table\n" , |
148 | component); |
149 | NL_SET_ERR_MSG_MOD(extack, "Component table conflict occurred" ); |
150 | break; |
151 | case ICE_AQ_NVM_PASS_COMP_PRE_REQ_NOT_MET_CODE: |
152 | dev_err(dev, "Pre-requisites for component %s have not been met\n" , |
153 | component); |
154 | NL_SET_ERR_MSG_MOD(extack, "Component pre-requisites not met" ); |
155 | break; |
156 | case ICE_AQ_NVM_PASS_COMP_NOT_SUPPORTED_CODE: |
157 | dev_err(dev, "%s is not a supported component\n" , |
158 | component); |
159 | NL_SET_ERR_MSG_MOD(extack, "Component not supported" ); |
160 | break; |
161 | case ICE_AQ_NVM_PASS_COMP_CANNOT_DOWNGRADE_CODE: |
162 | dev_err(dev, "Security restrictions prevent %s from being downgraded\n" , |
163 | component); |
164 | NL_SET_ERR_MSG_MOD(extack, "Component cannot be downgraded" ); |
165 | break; |
166 | case ICE_AQ_NVM_PASS_COMP_INCOMPLETE_IMAGE_CODE: |
167 | dev_err(dev, "Received an incomplete component image for %s\n" , |
168 | component); |
169 | NL_SET_ERR_MSG_MOD(extack, "Incomplete component image" ); |
170 | break; |
171 | case ICE_AQ_NVM_PASS_COMP_VER_STR_IDENTICAL_CODE: |
172 | dev_err(dev, "Component version for %s is identical to the running image\n" , |
173 | component); |
174 | NL_SET_ERR_MSG_MOD(extack, "Component version is identical to running image" ); |
175 | break; |
176 | case ICE_AQ_NVM_PASS_COMP_VER_STR_LOWER_CODE: |
177 | dev_err(dev, "Component version for %s is lower than the running image\n" , |
178 | component); |
179 | NL_SET_ERR_MSG_MOD(extack, "Component version is lower than the running image" ); |
180 | break; |
181 | default: |
182 | dev_err(dev, "Unexpected response code 0x02%x for %s\n" , |
183 | code, component); |
184 | NL_SET_ERR_MSG_MOD(extack, "Received unexpected response code from firmware" ); |
185 | break; |
186 | } |
187 | |
188 | return -ECANCELED; |
189 | } |
190 | |
191 | /** |
192 | * ice_send_component_table - Send PLDM component table to firmware |
193 | * @context: PLDM fw update structure |
194 | * @component: the component to process |
195 | * @transfer_flag: relative transfer order of this component |
196 | * |
197 | * Read relevant data from the component and forward it to the device |
198 | * firmware. Check the response to determine if the firmware indicates that |
199 | * the update can proceed. |
200 | * |
201 | * This function sends AdminQ commands related to the NVM, and assumes that |
202 | * the NVM resource has been acquired. |
203 | * |
204 | * Returns: zero on success, or a negative error code on failure. |
205 | */ |
206 | static int |
207 | ice_send_component_table(struct pldmfw *context, struct pldmfw_component *component, |
208 | u8 transfer_flag) |
209 | { |
210 | struct ice_fwu_priv *priv = container_of(context, struct ice_fwu_priv, context); |
211 | struct netlink_ext_ack *extack = priv->extack; |
212 | struct ice_aqc_nvm_comp_tbl *comp_tbl; |
213 | u8 comp_response, comp_response_code; |
214 | struct device *dev = context->dev; |
215 | struct ice_pf *pf = priv->pf; |
216 | struct ice_hw *hw = &pf->hw; |
217 | size_t length; |
218 | int status; |
219 | |
220 | switch (component->identifier) { |
221 | case NVM_COMP_ID_OROM: |
222 | case NVM_COMP_ID_NVM: |
223 | case NVM_COMP_ID_NETLIST: |
224 | break; |
225 | default: |
226 | dev_err(dev, "Unable to update due to a firmware component with unknown ID %u\n" , |
227 | component->identifier); |
228 | NL_SET_ERR_MSG_MOD(extack, "Unable to update due to unknown firmware component" ); |
229 | return -EOPNOTSUPP; |
230 | } |
231 | |
232 | length = struct_size(comp_tbl, cvs, component->version_len); |
233 | comp_tbl = kzalloc(size: length, GFP_KERNEL); |
234 | if (!comp_tbl) |
235 | return -ENOMEM; |
236 | |
237 | comp_tbl->comp_class = cpu_to_le16(component->classification); |
238 | comp_tbl->comp_id = cpu_to_le16(component->identifier); |
239 | comp_tbl->comp_class_idx = FWU_COMP_CLASS_IDX_NOT_USE; |
240 | comp_tbl->comp_cmp_stamp = cpu_to_le32(component->comparison_stamp); |
241 | comp_tbl->cvs_type = component->version_type; |
242 | comp_tbl->cvs_len = component->version_len; |
243 | memcpy(comp_tbl->cvs, component->version_string, component->version_len); |
244 | |
245 | dev_dbg(dev, "Sending component table to firmware:\n" ); |
246 | |
247 | status = ice_nvm_pass_component_tbl(hw, data: (u8 *)comp_tbl, length, |
248 | transfer_flag, comp_response: &comp_response, |
249 | comp_response_code: &comp_response_code, NULL); |
250 | |
251 | kfree(objp: comp_tbl); |
252 | |
253 | if (status) { |
254 | dev_err(dev, "Failed to transfer component table to firmware, err %d aq_err %s\n" , |
255 | status, ice_aq_str(hw->adminq.sq_last_status)); |
256 | NL_SET_ERR_MSG_MOD(extack, "Failed to transfer component table to firmware" ); |
257 | return -EIO; |
258 | } |
259 | |
260 | return ice_check_component_response(pf, id: component->identifier, response: comp_response, |
261 | code: comp_response_code, extack); |
262 | } |
263 | |
264 | /** |
265 | * ice_write_one_nvm_block - Write an NVM block and await completion response |
266 | * @pf: the PF data structure |
267 | * @module: the module to write to |
268 | * @offset: offset in bytes |
269 | * @block_size: size of the block to write, up to 4k |
270 | * @block: pointer to block of data to write |
271 | * @last_cmd: whether this is the last command |
272 | * @reset_level: storage for reset level required |
273 | * @extack: netlink extended ACK structure |
274 | * |
275 | * Write a block of data to a flash module, and await for the completion |
276 | * response message from firmware. |
277 | * |
278 | * Note this function assumes the caller has acquired the NVM resource. |
279 | * |
280 | * On successful return, reset level indicates the device reset required to |
281 | * complete the update. |
282 | * |
283 | * 0 - ICE_AQC_NVM_POR_FLAG - A full power on is required |
284 | * 1 - ICE_AQC_NVM_PERST_FLAG - A cold PCIe reset is required |
285 | * 2 - ICE_AQC_NVM_EMPR_FLAG - An EMP reset is required |
286 | * |
287 | * Returns: zero on success, or a negative error code on failure. |
288 | */ |
289 | static int |
290 | ice_write_one_nvm_block(struct ice_pf *pf, u16 module, u32 offset, |
291 | u16 block_size, u8 *block, bool last_cmd, |
292 | u8 *reset_level, struct netlink_ext_ack *extack) |
293 | { |
294 | u16 completion_module, completion_retval; |
295 | struct device *dev = ice_pf_to_dev(pf); |
296 | struct ice_aq_task task = {}; |
297 | struct ice_hw *hw = &pf->hw; |
298 | struct ice_aq_desc *desc; |
299 | u32 completion_offset; |
300 | int err; |
301 | |
302 | dev_dbg(dev, "Writing block of %u bytes for module 0x%02x at offset %u\n" , |
303 | block_size, module, offset); |
304 | |
305 | ice_aq_prep_for_event(pf, task: &task, opcode: ice_aqc_opc_nvm_write); |
306 | |
307 | err = ice_aq_update_nvm(hw, module_typeid: module, offset, length: block_size, data: block, |
308 | last_command: last_cmd, command_flags: 0, NULL); |
309 | if (err) { |
310 | dev_err(dev, "Failed to flash module 0x%02x with block of size %u at offset %u, err %d aq_err %s\n" , |
311 | module, block_size, offset, err, |
312 | ice_aq_str(hw->adminq.sq_last_status)); |
313 | NL_SET_ERR_MSG_MOD(extack, "Failed to program flash module" ); |
314 | return -EIO; |
315 | } |
316 | |
317 | /* In most cases, firmware reports a write completion within a few |
318 | * milliseconds. However, it has been observed that a completion might |
319 | * take more than a second to complete in some cases. The timeout here |
320 | * is conservative and is intended to prevent failure to update when |
321 | * firmware is slow to respond. |
322 | */ |
323 | err = ice_aq_wait_for_event(pf, task: &task, timeout: 15 * HZ); |
324 | if (err) { |
325 | dev_err(dev, "Timed out while trying to flash module 0x%02x with block of size %u at offset %u, err %d\n" , |
326 | module, block_size, offset, err); |
327 | NL_SET_ERR_MSG_MOD(extack, "Timed out waiting for firmware" ); |
328 | return -EIO; |
329 | } |
330 | |
331 | desc = &task.event.desc; |
332 | completion_module = le16_to_cpu(desc->params.nvm.module_typeid); |
333 | completion_retval = le16_to_cpu(desc->retval); |
334 | |
335 | completion_offset = le16_to_cpu(desc->params.nvm.offset_low); |
336 | completion_offset |= desc->params.nvm.offset_high << 16; |
337 | |
338 | if (completion_module != module) { |
339 | dev_err(dev, "Unexpected module_typeid in write completion: got 0x%x, expected 0x%x\n" , |
340 | completion_module, module); |
341 | NL_SET_ERR_MSG_MOD(extack, "Unexpected firmware response" ); |
342 | return -EIO; |
343 | } |
344 | |
345 | if (completion_offset != offset) { |
346 | dev_err(dev, "Unexpected offset in write completion: got %u, expected %u\n" , |
347 | completion_offset, offset); |
348 | NL_SET_ERR_MSG_MOD(extack, "Unexpected firmware response" ); |
349 | return -EIO; |
350 | } |
351 | |
352 | if (completion_retval) { |
353 | dev_err(dev, "Firmware failed to flash module 0x%02x with block of size %u at offset %u, err %s\n" , |
354 | module, block_size, offset, |
355 | ice_aq_str((enum ice_aq_err)completion_retval)); |
356 | NL_SET_ERR_MSG_MOD(extack, "Firmware failed to program flash module" ); |
357 | return -EIO; |
358 | } |
359 | |
360 | /* For the last command to write the NVM bank, newer versions of |
361 | * firmware indicate the required level of reset to complete |
362 | * activation of firmware. If the firmware supports this, cache the |
363 | * response for indicating to the user later. Otherwise, assume that |
364 | * a full power cycle is required. |
365 | */ |
366 | if (reset_level && last_cmd && module == ICE_SR_1ST_NVM_BANK_PTR) { |
367 | if (hw->dev_caps.common_cap.pcie_reset_avoidance) { |
368 | *reset_level = desc->params.nvm.cmd_flags & |
369 | ICE_AQC_NVM_RESET_LVL_M; |
370 | dev_dbg(dev, "Firmware reported required reset level as %u\n" , |
371 | *reset_level); |
372 | } else { |
373 | *reset_level = ICE_AQC_NVM_POR_FLAG; |
374 | dev_dbg(dev, "Firmware doesn't support indicating required reset level. Assuming a power cycle is required\n" ); |
375 | } |
376 | } |
377 | |
378 | return 0; |
379 | } |
380 | |
381 | /** |
382 | * ice_write_nvm_module - Write data to an NVM module |
383 | * @pf: the PF driver structure |
384 | * @module: the module id to program |
385 | * @component: the name of the component being updated |
386 | * @image: buffer of image data to write to the NVM |
387 | * @length: length of the buffer |
388 | * @reset_level: storage for reset level required |
389 | * @extack: netlink extended ACK structure |
390 | * |
391 | * Loop over the data for a given NVM module and program it in 4 Kb |
392 | * blocks. Notify devlink core of progress after each block is programmed. |
393 | * Loops over a block of data and programs the NVM in 4k block chunks. |
394 | * |
395 | * Note this function assumes the caller has acquired the NVM resource. |
396 | * |
397 | * Returns: zero on success, or a negative error code on failure. |
398 | */ |
399 | static int |
400 | ice_write_nvm_module(struct ice_pf *pf, u16 module, const char *component, |
401 | const u8 *image, u32 length, u8 *reset_level, |
402 | struct netlink_ext_ack *extack) |
403 | { |
404 | struct device *dev = ice_pf_to_dev(pf); |
405 | struct devlink *devlink; |
406 | u32 offset = 0; |
407 | bool last_cmd; |
408 | u8 *block; |
409 | int err; |
410 | |
411 | dev_dbg(dev, "Beginning write of flash component '%s', module 0x%02x\n" , component, module); |
412 | |
413 | devlink = priv_to_devlink(priv: pf); |
414 | |
415 | devlink_flash_update_status_notify(devlink, status_msg: "Flashing" , |
416 | component, done: 0, total: length); |
417 | |
418 | block = kzalloc(ICE_AQ_MAX_BUF_LEN, GFP_KERNEL); |
419 | if (!block) |
420 | return -ENOMEM; |
421 | |
422 | do { |
423 | u32 block_size; |
424 | |
425 | block_size = min_t(u32, ICE_AQ_MAX_BUF_LEN, length - offset); |
426 | last_cmd = !(offset + block_size < length); |
427 | |
428 | /* ice_aq_update_nvm may copy the firmware response into the |
429 | * buffer, so we must make a copy since the source data is |
430 | * constant. |
431 | */ |
432 | memcpy(block, image + offset, block_size); |
433 | |
434 | err = ice_write_one_nvm_block(pf, module, offset, block_size, |
435 | block, last_cmd, reset_level, |
436 | extack); |
437 | if (err) |
438 | break; |
439 | |
440 | offset += block_size; |
441 | |
442 | devlink_flash_update_status_notify(devlink, status_msg: "Flashing" , |
443 | component, done: offset, total: length); |
444 | } while (!last_cmd); |
445 | |
446 | dev_dbg(dev, "Completed write of flash component '%s', module 0x%02x\n" , component, module); |
447 | |
448 | if (err) |
449 | devlink_flash_update_status_notify(devlink, status_msg: "Flashing failed" , |
450 | component, done: length, total: length); |
451 | else |
452 | devlink_flash_update_status_notify(devlink, status_msg: "Flashing done" , |
453 | component, done: length, total: length); |
454 | |
455 | kfree(objp: block); |
456 | return err; |
457 | } |
458 | |
459 | /* Length in seconds to wait before timing out when erasing a flash module. |
460 | * Yes, erasing really can take minutes to complete. |
461 | */ |
462 | #define ICE_FW_ERASE_TIMEOUT 300 |
463 | |
464 | /** |
465 | * ice_erase_nvm_module - Erase an NVM module and await firmware completion |
466 | * @pf: the PF data structure |
467 | * @module: the module to erase |
468 | * @component: name of the component being updated |
469 | * @extack: netlink extended ACK structure |
470 | * |
471 | * Erase the inactive NVM bank associated with this module, and await for |
472 | * a completion response message from firmware. |
473 | * |
474 | * Note this function assumes the caller has acquired the NVM resource. |
475 | * |
476 | * Returns: zero on success, or a negative error code on failure. |
477 | */ |
478 | static int |
479 | ice_erase_nvm_module(struct ice_pf *pf, u16 module, const char *component, |
480 | struct netlink_ext_ack *extack) |
481 | { |
482 | u16 completion_module, completion_retval; |
483 | struct device *dev = ice_pf_to_dev(pf); |
484 | struct ice_aq_task task = {}; |
485 | struct ice_hw *hw = &pf->hw; |
486 | struct ice_aq_desc *desc; |
487 | struct devlink *devlink; |
488 | int err; |
489 | |
490 | dev_dbg(dev, "Beginning erase of flash component '%s', module 0x%02x\n" , component, module); |
491 | |
492 | devlink = priv_to_devlink(priv: pf); |
493 | |
494 | devlink_flash_update_timeout_notify(devlink, status_msg: "Erasing" , component, ICE_FW_ERASE_TIMEOUT); |
495 | |
496 | ice_aq_prep_for_event(pf, task: &task, opcode: ice_aqc_opc_nvm_erase); |
497 | |
498 | err = ice_aq_erase_nvm(hw, module_typeid: module, NULL); |
499 | if (err) { |
500 | dev_err(dev, "Failed to erase %s (module 0x%02x), err %d aq_err %s\n" , |
501 | component, module, err, |
502 | ice_aq_str(hw->adminq.sq_last_status)); |
503 | NL_SET_ERR_MSG_MOD(extack, "Failed to erase flash module" ); |
504 | err = -EIO; |
505 | goto out_notify_devlink; |
506 | } |
507 | |
508 | err = ice_aq_wait_for_event(pf, task: &task, ICE_FW_ERASE_TIMEOUT * HZ); |
509 | if (err) { |
510 | dev_err(dev, "Timed out waiting for firmware to respond with erase completion for %s (module 0x%02x), err %d\n" , |
511 | component, module, err); |
512 | NL_SET_ERR_MSG_MOD(extack, "Timed out waiting for firmware" ); |
513 | goto out_notify_devlink; |
514 | } |
515 | |
516 | desc = &task.event.desc; |
517 | completion_module = le16_to_cpu(desc->params.nvm.module_typeid); |
518 | completion_retval = le16_to_cpu(desc->retval); |
519 | |
520 | if (completion_module != module) { |
521 | dev_err(dev, "Unexpected module_typeid in erase completion for %s: got 0x%x, expected 0x%x\n" , |
522 | component, completion_module, module); |
523 | NL_SET_ERR_MSG_MOD(extack, "Unexpected firmware response" ); |
524 | err = -EIO; |
525 | goto out_notify_devlink; |
526 | } |
527 | |
528 | if (completion_retval) { |
529 | dev_err(dev, "Firmware failed to erase %s (module 0x02%x), aq_err %s\n" , |
530 | component, module, |
531 | ice_aq_str((enum ice_aq_err)completion_retval)); |
532 | NL_SET_ERR_MSG_MOD(extack, "Firmware failed to erase flash" ); |
533 | err = -EIO; |
534 | goto out_notify_devlink; |
535 | } |
536 | |
537 | dev_dbg(dev, "Completed erase of flash component '%s', module 0x%02x\n" , component, module); |
538 | |
539 | out_notify_devlink: |
540 | if (err) |
541 | devlink_flash_update_status_notify(devlink, status_msg: "Erasing failed" , |
542 | component, done: 0, total: 0); |
543 | else |
544 | devlink_flash_update_status_notify(devlink, status_msg: "Erasing done" , |
545 | component, done: 0, total: 0); |
546 | |
547 | return err; |
548 | } |
549 | |
550 | /** |
551 | * ice_switch_flash_banks - Tell firmware to switch NVM banks |
552 | * @pf: Pointer to the PF data structure |
553 | * @activate_flags: flags used for the activation command |
554 | * @emp_reset_available: on return, indicates if EMP reset is available |
555 | * @extack: netlink extended ACK structure |
556 | * |
557 | * Notify firmware to activate the newly written flash banks, and wait for the |
558 | * firmware response. |
559 | * |
560 | * Returns: zero on success or an error code on failure. |
561 | */ |
562 | static int |
563 | ice_switch_flash_banks(struct ice_pf *pf, u8 activate_flags, |
564 | u8 *emp_reset_available, struct netlink_ext_ack *extack) |
565 | { |
566 | struct device *dev = ice_pf_to_dev(pf); |
567 | struct ice_aq_task task = {}; |
568 | struct ice_hw *hw = &pf->hw; |
569 | u16 completion_retval; |
570 | u8 response_flags; |
571 | int err; |
572 | |
573 | ice_aq_prep_for_event(pf, task: &task, opcode: ice_aqc_opc_nvm_write_activate); |
574 | |
575 | err = ice_nvm_write_activate(hw, cmd_flags: activate_flags, response_flags: &response_flags); |
576 | if (err) { |
577 | dev_err(dev, "Failed to switch active flash banks, err %d aq_err %s\n" , |
578 | err, ice_aq_str(hw->adminq.sq_last_status)); |
579 | NL_SET_ERR_MSG_MOD(extack, "Failed to switch active flash banks" ); |
580 | return -EIO; |
581 | } |
582 | |
583 | /* Newer versions of firmware have support to indicate whether an EMP |
584 | * reset to reload firmware is available. For older firmware, EMP |
585 | * reset is always available. |
586 | */ |
587 | if (emp_reset_available) { |
588 | if (hw->dev_caps.common_cap.reset_restrict_support) { |
589 | *emp_reset_available = response_flags & ICE_AQC_NVM_EMPR_ENA; |
590 | dev_dbg(dev, "Firmware indicated that EMP reset is %s\n" , |
591 | *emp_reset_available ? |
592 | "available" : "not available" ); |
593 | } else { |
594 | *emp_reset_available = ICE_AQC_NVM_EMPR_ENA; |
595 | dev_dbg(dev, "Firmware does not support restricting EMP reset availability\n" ); |
596 | } |
597 | } |
598 | |
599 | err = ice_aq_wait_for_event(pf, task: &task, timeout: 30 * HZ); |
600 | if (err) { |
601 | dev_err(dev, "Timed out waiting for firmware to switch active flash banks, err %d\n" , |
602 | err); |
603 | NL_SET_ERR_MSG_MOD(extack, "Timed out waiting for firmware" ); |
604 | return err; |
605 | } |
606 | |
607 | completion_retval = le16_to_cpu(task.event.desc.retval); |
608 | if (completion_retval) { |
609 | dev_err(dev, "Firmware failed to switch active flash banks aq_err %s\n" , |
610 | ice_aq_str((enum ice_aq_err)completion_retval)); |
611 | NL_SET_ERR_MSG_MOD(extack, "Firmware failed to switch active flash banks" ); |
612 | return -EIO; |
613 | } |
614 | |
615 | return 0; |
616 | } |
617 | |
618 | /** |
619 | * ice_flash_component - Flash a component of the NVM |
620 | * @context: PLDM fw update structure |
621 | * @component: the component table to program |
622 | * |
623 | * Program the flash contents for a given component. First, determine the |
624 | * module id. Then, erase the secondary bank for this module. Finally, write |
625 | * the contents of the component to the NVM. |
626 | * |
627 | * Note this function assumes the caller has acquired the NVM resource. |
628 | * |
629 | * Returns: zero on success, or a negative error code on failure. |
630 | */ |
631 | static int |
632 | ice_flash_component(struct pldmfw *context, struct pldmfw_component *component) |
633 | { |
634 | struct ice_fwu_priv *priv = container_of(context, struct ice_fwu_priv, context); |
635 | struct netlink_ext_ack *extack = priv->extack; |
636 | struct ice_pf *pf = priv->pf; |
637 | const char *name; |
638 | u8 *reset_level; |
639 | u16 module; |
640 | u8 flag; |
641 | int err; |
642 | |
643 | switch (component->identifier) { |
644 | case NVM_COMP_ID_OROM: |
645 | module = ICE_SR_1ST_OROM_BANK_PTR; |
646 | flag = ICE_AQC_NVM_ACTIV_SEL_OROM; |
647 | reset_level = NULL; |
648 | name = "fw.undi" ; |
649 | break; |
650 | case NVM_COMP_ID_NVM: |
651 | module = ICE_SR_1ST_NVM_BANK_PTR; |
652 | flag = ICE_AQC_NVM_ACTIV_SEL_NVM; |
653 | reset_level = &priv->reset_level; |
654 | name = "fw.mgmt" ; |
655 | break; |
656 | case NVM_COMP_ID_NETLIST: |
657 | module = ICE_SR_NETLIST_BANK_PTR; |
658 | flag = ICE_AQC_NVM_ACTIV_SEL_NETLIST; |
659 | reset_level = NULL; |
660 | name = "fw.netlist" ; |
661 | break; |
662 | default: |
663 | /* This should not trigger, since we check the id before |
664 | * sending the component table to firmware. |
665 | */ |
666 | WARN(1, "Unexpected unknown component identifier 0x%02x" , |
667 | component->identifier); |
668 | return -EINVAL; |
669 | } |
670 | |
671 | /* Mark this component for activating at the end */ |
672 | priv->activate_flags |= flag; |
673 | |
674 | err = ice_erase_nvm_module(pf, module, component: name, extack); |
675 | if (err) |
676 | return err; |
677 | |
678 | return ice_write_nvm_module(pf, module, component: name, image: component->component_data, |
679 | length: component->component_size, reset_level, |
680 | extack); |
681 | } |
682 | |
683 | /** |
684 | * ice_finalize_update - Perform last steps to complete device update |
685 | * @context: PLDM fw update structure |
686 | * |
687 | * Called as the last step of the update process. Complete the update by |
688 | * telling the firmware to switch active banks, and perform a reset of |
689 | * configured. |
690 | * |
691 | * Returns: 0 on success, or an error code on failure. |
692 | */ |
693 | static int ice_finalize_update(struct pldmfw *context) |
694 | { |
695 | struct ice_fwu_priv *priv = container_of(context, struct ice_fwu_priv, context); |
696 | struct netlink_ext_ack *extack = priv->extack; |
697 | struct ice_pf *pf = priv->pf; |
698 | struct devlink *devlink; |
699 | int err; |
700 | |
701 | /* Finally, notify firmware to activate the written NVM banks */ |
702 | err = ice_switch_flash_banks(pf, activate_flags: priv->activate_flags, |
703 | emp_reset_available: &priv->emp_reset_available, extack); |
704 | if (err) |
705 | return err; |
706 | |
707 | devlink = priv_to_devlink(priv: pf); |
708 | |
709 | /* If the required reset is EMPR, but EMPR is disabled, report that |
710 | * a reboot is required instead. |
711 | */ |
712 | if (priv->reset_level == ICE_AQC_NVM_EMPR_FLAG && |
713 | !priv->emp_reset_available) { |
714 | dev_dbg(ice_pf_to_dev(pf), "Firmware indicated EMP reset as sufficient, but EMP reset is disabled\n" ); |
715 | priv->reset_level = ICE_AQC_NVM_PERST_FLAG; |
716 | } |
717 | |
718 | switch (priv->reset_level) { |
719 | case ICE_AQC_NVM_EMPR_FLAG: |
720 | devlink_flash_update_status_notify(devlink, |
721 | status_msg: "Activate new firmware by devlink reload" , |
722 | NULL, done: 0, total: 0); |
723 | break; |
724 | case ICE_AQC_NVM_PERST_FLAG: |
725 | devlink_flash_update_status_notify(devlink, |
726 | status_msg: "Activate new firmware by rebooting the system" , |
727 | NULL, done: 0, total: 0); |
728 | break; |
729 | case ICE_AQC_NVM_POR_FLAG: |
730 | default: |
731 | devlink_flash_update_status_notify(devlink, |
732 | status_msg: "Activate new firmware by power cycling the system" , |
733 | NULL, done: 0, total: 0); |
734 | break; |
735 | } |
736 | |
737 | pf->fw_emp_reset_disabled = !priv->emp_reset_available; |
738 | |
739 | return 0; |
740 | } |
741 | |
742 | struct ice_pldm_pci_record_id { |
743 | u32 vendor; |
744 | u32 device; |
745 | u32 subsystem_vendor; |
746 | u32 subsystem_device; |
747 | }; |
748 | |
749 | /** |
750 | * ice_op_pci_match_record - Check if a PCI device matches the record |
751 | * @context: PLDM fw update structure |
752 | * @record: list of records extracted from the PLDM image |
753 | * |
754 | * Determine if the PCI device associated with this device matches the record |
755 | * data provided. |
756 | * |
757 | * Searches the descriptor TLVs and extracts the relevant descriptor data into |
758 | * a pldm_pci_record_id. This is then compared against the PCI device ID |
759 | * information. |
760 | * |
761 | * Returns: true if the device matches the record, false otherwise. |
762 | */ |
763 | static bool |
764 | ice_op_pci_match_record(struct pldmfw *context, struct pldmfw_record *record) |
765 | { |
766 | struct pci_dev *pdev = to_pci_dev(context->dev); |
767 | struct ice_pldm_pci_record_id id = { |
768 | .vendor = PCI_ANY_ID, |
769 | .device = PCI_ANY_ID, |
770 | .subsystem_vendor = PCI_ANY_ID, |
771 | .subsystem_device = PCI_ANY_ID, |
772 | }; |
773 | struct pldmfw_desc_tlv *desc; |
774 | |
775 | list_for_each_entry(desc, &record->descs, entry) { |
776 | u16 value; |
777 | int *ptr; |
778 | |
779 | switch (desc->type) { |
780 | case PLDM_DESC_ID_PCI_VENDOR_ID: |
781 | ptr = &id.vendor; |
782 | break; |
783 | case PLDM_DESC_ID_PCI_DEVICE_ID: |
784 | ptr = &id.device; |
785 | break; |
786 | case PLDM_DESC_ID_PCI_SUBVENDOR_ID: |
787 | ptr = &id.subsystem_vendor; |
788 | break; |
789 | case PLDM_DESC_ID_PCI_SUBDEV_ID: |
790 | ptr = &id.subsystem_device; |
791 | break; |
792 | default: |
793 | /* Skip unrelated TLVs */ |
794 | continue; |
795 | } |
796 | |
797 | value = get_unaligned_le16(p: desc->data); |
798 | /* A value of zero for one of the descriptors is sometimes |
799 | * used when the record should ignore this field when matching |
800 | * device. For example if the record applies to any subsystem |
801 | * device or vendor. |
802 | */ |
803 | if (value) |
804 | *ptr = value; |
805 | else |
806 | *ptr = PCI_ANY_ID; |
807 | } |
808 | |
809 | /* the E822 device can have a generic device ID so check for that */ |
810 | if ((id.vendor == PCI_ANY_ID || id.vendor == pdev->vendor) && |
811 | (id.device == PCI_ANY_ID || id.device == pdev->device || |
812 | id.device == ICE_DEV_ID_E822_SI_DFLT) && |
813 | (id.subsystem_vendor == PCI_ANY_ID || |
814 | id.subsystem_vendor == pdev->subsystem_vendor) && |
815 | (id.subsystem_device == PCI_ANY_ID || |
816 | id.subsystem_device == pdev->subsystem_device)) |
817 | return true; |
818 | |
819 | return false; |
820 | } |
821 | |
822 | static const struct pldmfw_ops ice_fwu_ops_e810 = { |
823 | .match_record = &pldmfw_op_pci_match_record, |
824 | .send_package_data = &ice_send_package_data, |
825 | .send_component_table = &ice_send_component_table, |
826 | .flash_component = &ice_flash_component, |
827 | .finalize_update = &ice_finalize_update, |
828 | }; |
829 | |
830 | static const struct pldmfw_ops ice_fwu_ops_e822 = { |
831 | .match_record = &ice_op_pci_match_record, |
832 | .send_package_data = &ice_send_package_data, |
833 | .send_component_table = &ice_send_component_table, |
834 | .flash_component = &ice_flash_component, |
835 | .finalize_update = &ice_finalize_update, |
836 | }; |
837 | |
838 | /** |
839 | * ice_get_pending_updates - Check if the component has a pending update |
840 | * @pf: the PF driver structure |
841 | * @pending: on return, bitmap of updates pending |
842 | * @extack: Netlink extended ACK |
843 | * |
844 | * Check if the device has any pending updates on any flash components. |
845 | * |
846 | * Returns: zero on success, or a negative error code on failure. Updates |
847 | * pending with the bitmap of pending updates. |
848 | */ |
849 | int ice_get_pending_updates(struct ice_pf *pf, u8 *pending, |
850 | struct netlink_ext_ack *extack) |
851 | { |
852 | struct device *dev = ice_pf_to_dev(pf); |
853 | struct ice_hw_dev_caps *dev_caps; |
854 | struct ice_hw *hw = &pf->hw; |
855 | int err; |
856 | |
857 | dev_caps = kzalloc(size: sizeof(*dev_caps), GFP_KERNEL); |
858 | if (!dev_caps) |
859 | return -ENOMEM; |
860 | |
861 | /* Read the most recent device capabilities from firmware. Do not use |
862 | * the cached values in hw->dev_caps, because the pending update flag |
863 | * may have changed, e.g. if an update was previously completed and |
864 | * the system has not yet rebooted. |
865 | */ |
866 | err = ice_discover_dev_caps(hw, dev_caps); |
867 | if (err) { |
868 | NL_SET_ERR_MSG_MOD(extack, "Unable to read device capabilities" ); |
869 | kfree(objp: dev_caps); |
870 | return err; |
871 | } |
872 | |
873 | *pending = 0; |
874 | |
875 | if (dev_caps->common_cap.nvm_update_pending_nvm) { |
876 | dev_info(dev, "The fw.mgmt flash component has a pending update\n" ); |
877 | *pending |= ICE_AQC_NVM_ACTIV_SEL_NVM; |
878 | } |
879 | |
880 | if (dev_caps->common_cap.nvm_update_pending_orom) { |
881 | dev_info(dev, "The fw.undi flash component has a pending update\n" ); |
882 | *pending |= ICE_AQC_NVM_ACTIV_SEL_OROM; |
883 | } |
884 | |
885 | if (dev_caps->common_cap.nvm_update_pending_netlist) { |
886 | dev_info(dev, "The fw.netlist flash component has a pending update\n" ); |
887 | *pending |= ICE_AQC_NVM_ACTIV_SEL_NETLIST; |
888 | } |
889 | |
890 | kfree(objp: dev_caps); |
891 | |
892 | return 0; |
893 | } |
894 | |
895 | /** |
896 | * ice_cancel_pending_update - Cancel any pending update for a component |
897 | * @pf: the PF driver structure |
898 | * @component: if not NULL, the name of the component being updated |
899 | * @extack: Netlink extended ACK structure |
900 | * |
901 | * Cancel any pending update for the specified component. If component is |
902 | * NULL, all device updates will be canceled. |
903 | * |
904 | * Returns: zero on success, or a negative error code on failure. |
905 | */ |
906 | static int |
907 | ice_cancel_pending_update(struct ice_pf *pf, const char *component, |
908 | struct netlink_ext_ack *extack) |
909 | { |
910 | struct devlink *devlink = priv_to_devlink(priv: pf); |
911 | struct device *dev = ice_pf_to_dev(pf); |
912 | struct ice_hw *hw = &pf->hw; |
913 | u8 pending; |
914 | int err; |
915 | |
916 | err = ice_get_pending_updates(pf, pending: &pending, extack); |
917 | if (err) |
918 | return err; |
919 | |
920 | /* If the flash_update request is for a specific component, ignore all |
921 | * of the other components. |
922 | */ |
923 | if (component) { |
924 | if (strcmp(component, "fw.mgmt" ) == 0) |
925 | pending &= ICE_AQC_NVM_ACTIV_SEL_NVM; |
926 | else if (strcmp(component, "fw.undi" ) == 0) |
927 | pending &= ICE_AQC_NVM_ACTIV_SEL_OROM; |
928 | else if (strcmp(component, "fw.netlist" ) == 0) |
929 | pending &= ICE_AQC_NVM_ACTIV_SEL_NETLIST; |
930 | else |
931 | WARN(1, "Unexpected flash component %s" , component); |
932 | } |
933 | |
934 | /* There is no previous pending update, so this request may continue */ |
935 | if (!pending) |
936 | return 0; |
937 | |
938 | /* In order to allow overwriting a previous pending update, notify |
939 | * firmware to cancel that update by issuing the appropriate command. |
940 | */ |
941 | devlink_flash_update_status_notify(devlink, |
942 | status_msg: "Canceling previous pending update" , |
943 | component, done: 0, total: 0); |
944 | |
945 | err = ice_acquire_nvm(hw, access: ICE_RES_WRITE); |
946 | if (err) { |
947 | dev_err(dev, "Failed to acquire device flash lock, err %d aq_err %s\n" , |
948 | err, ice_aq_str(hw->adminq.sq_last_status)); |
949 | NL_SET_ERR_MSG_MOD(extack, "Failed to acquire device flash lock" ); |
950 | return err; |
951 | } |
952 | |
953 | pending |= ICE_AQC_NVM_REVERT_LAST_ACTIV; |
954 | err = ice_switch_flash_banks(pf, activate_flags: pending, NULL, extack); |
955 | |
956 | ice_release_nvm(hw); |
957 | |
958 | /* Since we've canceled the pending update, we no longer know if EMP |
959 | * reset is restricted. |
960 | */ |
961 | pf->fw_emp_reset_disabled = false; |
962 | |
963 | return err; |
964 | } |
965 | |
966 | /** |
967 | * ice_devlink_flash_update - Write a firmware image to the device |
968 | * @devlink: pointer to devlink associated with the device to update |
969 | * @params: devlink flash update parameters |
970 | * @extack: netlink extended ACK structure |
971 | * |
972 | * Parse the data for a given firmware file, verifying that it is a valid PLDM |
973 | * formatted image that matches this device. |
974 | * |
975 | * Extract the device record Package Data and Component Tables and send them |
976 | * to the firmware. Extract and write the flash data for each of the three |
977 | * main flash components, "fw.mgmt", "fw.undi", and "fw.netlist". Notify |
978 | * firmware once the data is written to the inactive banks. |
979 | * |
980 | * Returns: zero on success or a negative error code on failure. |
981 | */ |
982 | int ice_devlink_flash_update(struct devlink *devlink, |
983 | struct devlink_flash_update_params *params, |
984 | struct netlink_ext_ack *extack) |
985 | { |
986 | struct ice_pf *pf = devlink_priv(devlink); |
987 | struct device *dev = ice_pf_to_dev(pf); |
988 | struct ice_hw *hw = &pf->hw; |
989 | struct ice_fwu_priv priv; |
990 | u8 preservation; |
991 | int err; |
992 | |
993 | if (!params->overwrite_mask) { |
994 | /* preserve all settings and identifiers */ |
995 | preservation = ICE_AQC_NVM_PRESERVE_ALL; |
996 | } else if (params->overwrite_mask == DEVLINK_FLASH_OVERWRITE_SETTINGS) { |
997 | /* overwrite settings, but preserve the vital device identifiers */ |
998 | preservation = ICE_AQC_NVM_PRESERVE_SELECTED; |
999 | } else if (params->overwrite_mask == (DEVLINK_FLASH_OVERWRITE_SETTINGS | |
1000 | DEVLINK_FLASH_OVERWRITE_IDENTIFIERS)) { |
1001 | /* overwrite both settings and identifiers, preserve nothing */ |
1002 | preservation = ICE_AQC_NVM_NO_PRESERVATION; |
1003 | } else { |
1004 | NL_SET_ERR_MSG_MOD(extack, "Requested overwrite mask is not supported" ); |
1005 | return -EOPNOTSUPP; |
1006 | } |
1007 | |
1008 | if (!hw->dev_caps.common_cap.nvm_unified_update) { |
1009 | NL_SET_ERR_MSG_MOD(extack, "Current firmware does not support unified update" ); |
1010 | return -EOPNOTSUPP; |
1011 | } |
1012 | |
1013 | memset(&priv, 0, sizeof(priv)); |
1014 | |
1015 | /* the E822 device needs a slightly different ops */ |
1016 | if (hw->mac_type == ICE_MAC_GENERIC) |
1017 | priv.context.ops = &ice_fwu_ops_e822; |
1018 | else |
1019 | priv.context.ops = &ice_fwu_ops_e810; |
1020 | priv.context.dev = dev; |
1021 | priv.extack = extack; |
1022 | priv.pf = pf; |
1023 | priv.activate_flags = preservation; |
1024 | |
1025 | devlink_flash_update_status_notify(devlink, status_msg: "Preparing to flash" , NULL, done: 0, total: 0); |
1026 | |
1027 | err = ice_cancel_pending_update(pf, NULL, extack); |
1028 | if (err) |
1029 | return err; |
1030 | |
1031 | err = ice_acquire_nvm(hw, access: ICE_RES_WRITE); |
1032 | if (err) { |
1033 | dev_err(dev, "Failed to acquire device flash lock, err %d aq_err %s\n" , |
1034 | err, ice_aq_str(hw->adminq.sq_last_status)); |
1035 | NL_SET_ERR_MSG_MOD(extack, "Failed to acquire device flash lock" ); |
1036 | return err; |
1037 | } |
1038 | |
1039 | err = pldmfw_flash_image(context: &priv.context, fw: params->fw); |
1040 | if (err == -ENOENT) { |
1041 | dev_err(dev, "Firmware image has no record matching this device\n" ); |
1042 | NL_SET_ERR_MSG_MOD(extack, "Firmware image has no record matching this device" ); |
1043 | } else if (err) { |
1044 | /* Do not set a generic extended ACK message here. A more |
1045 | * specific message may already have been set by one of our |
1046 | * ops. |
1047 | */ |
1048 | dev_err(dev, "Failed to flash PLDM image, err %d" , err); |
1049 | } |
1050 | |
1051 | ice_release_nvm(hw); |
1052 | |
1053 | return err; |
1054 | } |
1055 | |