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>
This commit is contained in:
@@ -368,14 +368,18 @@ static int ice_devlink_info_get(struct devlink *devlink,
|
||||
}
|
||||
break;
|
||||
case ICE_VERSION_RUNNING:
|
||||
err = devlink_info_version_running_put(req, key, ctx->buf);
|
||||
err = devlink_info_version_running_put_ext(req, key,
|
||||
ctx->buf,
|
||||
DEVLINK_INFO_VERSION_TYPE_COMPONENT);
|
||||
if (err) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Unable to set running version");
|
||||
goto out_free_ctx;
|
||||
}
|
||||
break;
|
||||
case ICE_VERSION_STORED:
|
||||
err = devlink_info_version_stored_put(req, key, ctx->buf);
|
||||
err = devlink_info_version_stored_put_ext(req, key,
|
||||
ctx->buf,
|
||||
DEVLINK_INFO_VERSION_TYPE_COMPONENT);
|
||||
if (err) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version");
|
||||
goto out_free_ctx;
|
||||
|
||||
@@ -1815,6 +1815,7 @@ struct ice_aqc_nvm_pass_comp_tbl {
|
||||
#define ICE_AQ_NVM_PASS_COMP_CAN_BE_UPDATED 0x0
|
||||
#define ICE_AQ_NVM_PASS_COMP_CAN_MAY_BE_UPDATEABLE 0x1
|
||||
#define ICE_AQ_NVM_PASS_COMP_CAN_NOT_BE_UPDATED 0x2
|
||||
#define ICE_AQ_NVM_PASS_COMP_PARTIAL_CHECK 0x3
|
||||
u8 component_response_code; /* Response only */
|
||||
#define ICE_AQ_NVM_PASS_COMP_CAN_BE_UPDATED_CODE 0x0
|
||||
#define ICE_AQ_NVM_PASS_COMP_STAMP_IDENTICAL_CODE 0x1
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/pldmfw.h>
|
||||
#include "ice.h"
|
||||
#include "ice_lib.h"
|
||||
#include "ice_fw_update.h"
|
||||
|
||||
struct ice_fwu_priv {
|
||||
@@ -125,6 +126,10 @@ ice_check_component_response(struct ice_pf *pf, u16 id, u8 response, u8 code,
|
||||
case ICE_AQ_NVM_PASS_COMP_CAN_NOT_BE_UPDATED:
|
||||
dev_info(dev, "firmware has rejected updating %s\n", component);
|
||||
break;
|
||||
case ICE_AQ_NVM_PASS_COMP_PARTIAL_CHECK:
|
||||
if (ice_is_recovery_mode(&pf->hw))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
@@ -1004,13 +1009,20 @@ int ice_devlink_flash_update(struct devlink *devlink,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (!hw->dev_caps.common_cap.nvm_unified_update) {
|
||||
if (!hw->dev_caps.common_cap.nvm_unified_update && !ice_is_recovery_mode(hw)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Current firmware does not support unified update");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
memset(&priv, 0, sizeof(priv));
|
||||
|
||||
if (params->component && strcmp(params->component, "fw.mgmt") == 0) {
|
||||
priv.context.mode = PLDMFW_UPDATE_MODE_SINGLE_COMPONENT;
|
||||
priv.context.component_identifier = NVM_COMP_ID_NVM;
|
||||
} else if (params->component) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* the E822 device needs a slightly different ops */
|
||||
if (hw->mac_type == ICE_MAC_GENERIC)
|
||||
priv.context.ops = &ice_fwu_ops_e822;
|
||||
|
||||
@@ -1700,6 +1700,12 @@ bool ice_pf_state_is_nominal(struct ice_pf *pf)
|
||||
return true;
|
||||
}
|
||||
|
||||
#define ICE_FW_MODE_REC_M BIT(1)
|
||||
bool ice_is_recovery_mode(struct ice_hw *hw)
|
||||
{
|
||||
return rd32(hw, GL_MNG_FWSM) & ICE_FW_MODE_REC_M;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_update_eth_stats - Update VSI-specific ethernet statistics counters
|
||||
* @vsi: the VSI to be updated
|
||||
|
||||
@@ -90,6 +90,7 @@ void ice_set_q_vector_intrl(struct ice_q_vector *q_vector);
|
||||
|
||||
bool ice_is_safe_mode(struct ice_pf *pf);
|
||||
bool ice_is_rdma_ena(struct ice_pf *pf);
|
||||
bool ice_is_recovery_mode(struct ice_hw *hw);
|
||||
bool ice_is_dflt_vsi_in_use(struct ice_port_info *pi);
|
||||
bool ice_is_vsi_dflt_vsi(struct ice_vsi *vsi);
|
||||
int ice_set_dflt_vsi(struct ice_vsi *vsi);
|
||||
|
||||
@@ -2364,6 +2364,18 @@ static void ice_check_media_subtask(struct ice_pf *pf)
|
||||
}
|
||||
}
|
||||
|
||||
static void ice_service_task_recovery_mode(struct work_struct *work)
|
||||
{
|
||||
struct ice_pf *pf = container_of(work, struct ice_pf, serv_task);
|
||||
|
||||
set_bit(ICE_ADMINQ_EVENT_PENDING, pf->state);
|
||||
ice_clean_adminq_subtask(pf);
|
||||
|
||||
ice_service_task_complete(pf);
|
||||
|
||||
mod_timer(&pf->serv_tmr, jiffies + msecs_to_jiffies(100));
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_service_task - manage and run subtasks
|
||||
* @work: pointer to work_struct contained by the PF struct
|
||||
@@ -5217,6 +5229,36 @@ void ice_unload(struct ice_pf *pf)
|
||||
ice_decfg_netdev(vsi);
|
||||
}
|
||||
|
||||
static int ice_probe_recovery_mode(struct ice_pf *pf)
|
||||
{
|
||||
struct device *dev = ice_pf_to_dev(pf);
|
||||
int err;
|
||||
|
||||
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");
|
||||
|
||||
INIT_HLIST_HEAD(&pf->aq_wait_list);
|
||||
spin_lock_init(&pf->aq_wait_lock);
|
||||
init_waitqueue_head(&pf->aq_wait_queue);
|
||||
|
||||
timer_setup(&pf->serv_tmr, ice_service_timer, 0);
|
||||
pf->serv_tmr_period = HZ;
|
||||
INIT_WORK(&pf->serv_task, ice_service_task_recovery_mode);
|
||||
clear_bit(ICE_SERVICE_SCHED, pf->state);
|
||||
err = ice_create_all_ctrlq(&pf->hw);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
scoped_guard(devl, priv_to_devlink(pf)) {
|
||||
err = ice_init_devlink(pf);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
ice_service_task_restart(pf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_probe - Device initialization routine
|
||||
* @pdev: PCI device information struct
|
||||
@@ -5308,6 +5350,9 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
|
||||
hw->debug_mask = debug;
|
||||
#endif
|
||||
|
||||
if (ice_is_recovery_mode(hw))
|
||||
return ice_probe_recovery_mode(pf);
|
||||
|
||||
err = ice_init_hw(hw);
|
||||
if (err) {
|
||||
dev_err(dev, "ice_init_hw failed: %d\n", err);
|
||||
@@ -5425,6 +5470,14 @@ static void ice_remove(struct pci_dev *pdev)
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
if (ice_is_recovery_mode(&pf->hw)) {
|
||||
ice_service_task_stop(pf);
|
||||
scoped_guard(devl, priv_to_devlink(pf)) {
|
||||
ice_deinit_devlink(pf);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (test_bit(ICE_FLAG_SRIOV_ENA, pf->flags)) {
|
||||
set_bit(ICE_VF_RESETS_DISABLED, pf->state);
|
||||
ice_free_vfs(pf);
|
||||
|
||||
@@ -125,9 +125,17 @@ struct pldmfw_ops;
|
||||
* a pointer to their own data, used to implement the device specific
|
||||
* operations.
|
||||
*/
|
||||
|
||||
enum pldmfw_update_mode {
|
||||
PLDMFW_UPDATE_MODE_FULL,
|
||||
PLDMFW_UPDATE_MODE_SINGLE_COMPONENT,
|
||||
};
|
||||
|
||||
struct pldmfw {
|
||||
const struct pldmfw_ops *ops;
|
||||
struct device *dev;
|
||||
u16 component_identifier;
|
||||
enum pldmfw_update_mode mode;
|
||||
};
|
||||
|
||||
bool pldmfw_op_pci_match_record(struct pldmfw *context, struct pldmfw_record *record);
|
||||
|
||||
@@ -1535,6 +1535,7 @@ int devl_trylock(struct devlink *devlink);
|
||||
void devl_unlock(struct devlink *devlink);
|
||||
void devl_assert_locked(struct devlink *devlink);
|
||||
bool devl_lock_is_held(struct devlink *devlink);
|
||||
DEFINE_GUARD(devl, struct devlink *, devl_lock(_T), devl_unlock(_T));
|
||||
|
||||
struct ib_device;
|
||||
|
||||
|
||||
@@ -481,9 +481,17 @@ static int pldm_parse_components(struct pldmfw_priv *data)
|
||||
component->component_data = data->fw->data + offset;
|
||||
component->component_size = size;
|
||||
|
||||
if (data->context->mode == PLDMFW_UPDATE_MODE_SINGLE_COMPONENT &&
|
||||
data->context->component_identifier != component->identifier)
|
||||
continue;
|
||||
|
||||
list_add_tail(&component->entry, &data->components);
|
||||
}
|
||||
|
||||
if (data->context->mode == PLDMFW_UPDATE_MODE_SINGLE_COMPONENT &&
|
||||
list_empty(&data->components))
|
||||
return -ENOENT;
|
||||
|
||||
header_crc_ptr = data->fw->data + data->offset;
|
||||
|
||||
err = pldm_move_fw_offset(data, sizeof(data->header_crc));
|
||||
|
||||
Reference in New Issue
Block a user