Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue

Tony Nguyen says:

====================
ice: support FW Recovery Mode

Konrad Knitter says:

Enable update of card in FW Recovery Mode

* '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue:
ice: support FW Recovery Mode
devlink: add devl guard
pldmfw: enable selected component update
====================

Link: https://patch.msgid.link/20250116212059.1254349-1-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+97 -3
+6 -2
drivers/net/ethernet/intel/ice/devlink/devlink.c
··· 368 368 } 369 369 break; 370 370 case ICE_VERSION_RUNNING: 371 - err = devlink_info_version_running_put(req, key, ctx->buf); 371 + err = devlink_info_version_running_put_ext(req, key, 372 + ctx->buf, 373 + DEVLINK_INFO_VERSION_TYPE_COMPONENT); 372 374 if (err) { 373 375 NL_SET_ERR_MSG_MOD(extack, "Unable to set running version"); 374 376 goto out_free_ctx; 375 377 } 376 378 break; 377 379 case ICE_VERSION_STORED: 378 - err = devlink_info_version_stored_put(req, key, ctx->buf); 380 + err = devlink_info_version_stored_put_ext(req, key, 381 + ctx->buf, 382 + DEVLINK_INFO_VERSION_TYPE_COMPONENT); 379 383 if (err) { 380 384 NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version"); 381 385 goto out_free_ctx;
+1
drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
··· 1815 1815 #define ICE_AQ_NVM_PASS_COMP_CAN_BE_UPDATED 0x0 1816 1816 #define ICE_AQ_NVM_PASS_COMP_CAN_MAY_BE_UPDATEABLE 0x1 1817 1817 #define ICE_AQ_NVM_PASS_COMP_CAN_NOT_BE_UPDATED 0x2 1818 + #define ICE_AQ_NVM_PASS_COMP_PARTIAL_CHECK 0x3 1818 1819 u8 component_response_code; /* Response only */ 1819 1820 #define ICE_AQ_NVM_PASS_COMP_CAN_BE_UPDATED_CODE 0x0 1820 1821 #define ICE_AQ_NVM_PASS_COMP_STAMP_IDENTICAL_CODE 0x1
+13 -1
drivers/net/ethernet/intel/ice/ice_fw_update.c
··· 6 6 #include <linux/crc32.h> 7 7 #include <linux/pldmfw.h> 8 8 #include "ice.h" 9 + #include "ice_lib.h" 9 10 #include "ice_fw_update.h" 10 11 11 12 struct ice_fwu_priv { ··· 125 124 return 0; 126 125 case ICE_AQ_NVM_PASS_COMP_CAN_NOT_BE_UPDATED: 127 126 dev_info(dev, "firmware has rejected updating %s\n", component); 127 + break; 128 + case ICE_AQ_NVM_PASS_COMP_PARTIAL_CHECK: 129 + if (ice_is_recovery_mode(&pf->hw)) 130 + return 0; 128 131 break; 129 132 } 130 133 ··· 1009 1004 return -EOPNOTSUPP; 1010 1005 } 1011 1006 1012 - if (!hw->dev_caps.common_cap.nvm_unified_update) { 1007 + if (!hw->dev_caps.common_cap.nvm_unified_update && !ice_is_recovery_mode(hw)) { 1013 1008 NL_SET_ERR_MSG_MOD(extack, "Current firmware does not support unified update"); 1014 1009 return -EOPNOTSUPP; 1015 1010 } 1016 1011 1017 1012 memset(&priv, 0, sizeof(priv)); 1013 + 1014 + if (params->component && strcmp(params->component, "fw.mgmt") == 0) { 1015 + priv.context.mode = PLDMFW_UPDATE_MODE_SINGLE_COMPONENT; 1016 + priv.context.component_identifier = NVM_COMP_ID_NVM; 1017 + } else if (params->component) { 1018 + return -EOPNOTSUPP; 1019 + } 1018 1020 1019 1021 /* the E822 device needs a slightly different ops */ 1020 1022 if (hw->mac_type == ICE_MAC_GENERIC)
+6
drivers/net/ethernet/intel/ice/ice_lib.c
··· 1700 1700 return true; 1701 1701 } 1702 1702 1703 + #define ICE_FW_MODE_REC_M BIT(1) 1704 + bool ice_is_recovery_mode(struct ice_hw *hw) 1705 + { 1706 + return rd32(hw, GL_MNG_FWSM) & ICE_FW_MODE_REC_M; 1707 + } 1708 + 1703 1709 /** 1704 1710 * ice_update_eth_stats - Update VSI-specific ethernet statistics counters 1705 1711 * @vsi: the VSI to be updated
+1
drivers/net/ethernet/intel/ice/ice_lib.h
··· 90 90 91 91 bool ice_is_safe_mode(struct ice_pf *pf); 92 92 bool ice_is_rdma_ena(struct ice_pf *pf); 93 + bool ice_is_recovery_mode(struct ice_hw *hw); 93 94 bool ice_is_dflt_vsi_in_use(struct ice_port_info *pi); 94 95 bool ice_is_vsi_dflt_vsi(struct ice_vsi *vsi); 95 96 int ice_set_dflt_vsi(struct ice_vsi *vsi);
+53
drivers/net/ethernet/intel/ice/ice_main.c
··· 2364 2364 } 2365 2365 } 2366 2366 2367 + static void ice_service_task_recovery_mode(struct work_struct *work) 2368 + { 2369 + struct ice_pf *pf = container_of(work, struct ice_pf, serv_task); 2370 + 2371 + set_bit(ICE_ADMINQ_EVENT_PENDING, pf->state); 2372 + ice_clean_adminq_subtask(pf); 2373 + 2374 + ice_service_task_complete(pf); 2375 + 2376 + mod_timer(&pf->serv_tmr, jiffies + msecs_to_jiffies(100)); 2377 + } 2378 + 2367 2379 /** 2368 2380 * ice_service_task - manage and run subtasks 2369 2381 * @work: pointer to work_struct contained by the PF struct ··· 5229 5217 ice_decfg_netdev(vsi); 5230 5218 } 5231 5219 5220 + static int ice_probe_recovery_mode(struct ice_pf *pf) 5221 + { 5222 + struct device *dev = ice_pf_to_dev(pf); 5223 + int err; 5224 + 5225 + dev_err(dev, "Firmware recovery mode detected. Limiting functionality. Refer to the Intel(R) Ethernet Adapters and Devices User Guide for details on firmware recovery mode\n"); 5226 + 5227 + INIT_HLIST_HEAD(&pf->aq_wait_list); 5228 + spin_lock_init(&pf->aq_wait_lock); 5229 + init_waitqueue_head(&pf->aq_wait_queue); 5230 + 5231 + timer_setup(&pf->serv_tmr, ice_service_timer, 0); 5232 + pf->serv_tmr_period = HZ; 5233 + INIT_WORK(&pf->serv_task, ice_service_task_recovery_mode); 5234 + clear_bit(ICE_SERVICE_SCHED, pf->state); 5235 + err = ice_create_all_ctrlq(&pf->hw); 5236 + if (err) 5237 + return err; 5238 + 5239 + scoped_guard(devl, priv_to_devlink(pf)) { 5240 + err = ice_init_devlink(pf); 5241 + if (err) 5242 + return err; 5243 + } 5244 + 5245 + ice_service_task_restart(pf); 5246 + 5247 + return 0; 5248 + } 5249 + 5232 5250 /** 5233 5251 * ice_probe - Device initialization routine 5234 5252 * @pdev: PCI device information struct ··· 5349 5307 if (debug < -1) 5350 5308 hw->debug_mask = debug; 5351 5309 #endif 5310 + 5311 + if (ice_is_recovery_mode(hw)) 5312 + return ice_probe_recovery_mode(pf); 5352 5313 5353 5314 err = ice_init_hw(hw); 5354 5315 if (err) { ··· 5468 5423 if (!ice_is_reset_in_progress(pf->state)) 5469 5424 break; 5470 5425 msleep(100); 5426 + } 5427 + 5428 + if (ice_is_recovery_mode(&pf->hw)) { 5429 + ice_service_task_stop(pf); 5430 + scoped_guard(devl, priv_to_devlink(pf)) { 5431 + ice_deinit_devlink(pf); 5432 + } 5433 + return; 5471 5434 } 5472 5435 5473 5436 if (test_bit(ICE_FLAG_SRIOV_ENA, pf->flags)) {
+8
include/linux/pldmfw.h
··· 125 125 * a pointer to their own data, used to implement the device specific 126 126 * operations. 127 127 */ 128 + 129 + enum pldmfw_update_mode { 130 + PLDMFW_UPDATE_MODE_FULL, 131 + PLDMFW_UPDATE_MODE_SINGLE_COMPONENT, 132 + }; 133 + 128 134 struct pldmfw { 129 135 const struct pldmfw_ops *ops; 130 136 struct device *dev; 137 + u16 component_identifier; 138 + enum pldmfw_update_mode mode; 131 139 }; 132 140 133 141 bool pldmfw_op_pci_match_record(struct pldmfw *context, struct pldmfw_record *record);
+1
include/net/devlink.h
··· 1535 1535 void devl_unlock(struct devlink *devlink); 1536 1536 void devl_assert_locked(struct devlink *devlink); 1537 1537 bool devl_lock_is_held(struct devlink *devlink); 1538 + DEFINE_GUARD(devl, struct devlink *, devl_lock(_T), devl_unlock(_T)); 1538 1539 1539 1540 struct ib_device; 1540 1541
+8
lib/pldmfw/pldmfw.c
··· 481 481 component->component_data = data->fw->data + offset; 482 482 component->component_size = size; 483 483 484 + if (data->context->mode == PLDMFW_UPDATE_MODE_SINGLE_COMPONENT && 485 + data->context->component_identifier != component->identifier) 486 + continue; 487 + 484 488 list_add_tail(&component->entry, &data->components); 485 489 } 490 + 491 + if (data->context->mode == PLDMFW_UPDATE_MODE_SINGLE_COMPONENT && 492 + list_empty(&data->components)) 493 + return -ENOENT; 486 494 487 495 header_crc_ptr = data->fw->data + data->offset; 488 496