Skip to content

Commit ba0209b

Browse files
committed
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>
2 parents 3df22e7 + 1de25c6 commit ba0209b

File tree

9 files changed

+97
-3
lines changed

9 files changed

+97
-3
lines changed

drivers/net/ethernet/intel/ice/devlink/devlink.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,14 +368,18 @@ static int ice_devlink_info_get(struct devlink *devlink,
368368
}
369369
break;
370370
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);
372374
if (err) {
373375
NL_SET_ERR_MSG_MOD(extack, "Unable to set running version");
374376
goto out_free_ctx;
375377
}
376378
break;
377379
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);
379383
if (err) {
380384
NL_SET_ERR_MSG_MOD(extack, "Unable to set stored version");
381385
goto out_free_ctx;

drivers/net/ethernet/intel/ice/ice_adminq_cmd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1815,6 +1815,7 @@ struct ice_aqc_nvm_pass_comp_tbl {
18151815
#define ICE_AQ_NVM_PASS_COMP_CAN_BE_UPDATED 0x0
18161816
#define ICE_AQ_NVM_PASS_COMP_CAN_MAY_BE_UPDATEABLE 0x1
18171817
#define ICE_AQ_NVM_PASS_COMP_CAN_NOT_BE_UPDATED 0x2
1818+
#define ICE_AQ_NVM_PASS_COMP_PARTIAL_CHECK 0x3
18181819
u8 component_response_code; /* Response only */
18191820
#define ICE_AQ_NVM_PASS_COMP_CAN_BE_UPDATED_CODE 0x0
18201821
#define ICE_AQ_NVM_PASS_COMP_STAMP_IDENTICAL_CODE 0x1

drivers/net/ethernet/intel/ice/ice_fw_update.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/crc32.h>
77
#include <linux/pldmfw.h>
88
#include "ice.h"
9+
#include "ice_lib.h"
910
#include "ice_fw_update.h"
1011

1112
struct ice_fwu_priv {
@@ -125,6 +126,10 @@ ice_check_component_response(struct ice_pf *pf, u16 id, u8 response, u8 code,
125126
case ICE_AQ_NVM_PASS_COMP_CAN_NOT_BE_UPDATED:
126127
dev_info(dev, "firmware has rejected updating %s\n", component);
127128
break;
129+
case ICE_AQ_NVM_PASS_COMP_PARTIAL_CHECK:
130+
if (ice_is_recovery_mode(&pf->hw))
131+
return 0;
132+
break;
128133
}
129134

130135
switch (code) {
@@ -1004,13 +1009,20 @@ int ice_devlink_flash_update(struct devlink *devlink,
10041009
return -EOPNOTSUPP;
10051010
}
10061011

1007-
if (!hw->dev_caps.common_cap.nvm_unified_update) {
1012+
if (!hw->dev_caps.common_cap.nvm_unified_update && !ice_is_recovery_mode(hw)) {
10081013
NL_SET_ERR_MSG_MOD(extack, "Current firmware does not support unified update");
10091014
return -EOPNOTSUPP;
10101015
}
10111016

10121017
memset(&priv, 0, sizeof(priv));
10131018

1019+
if (params->component && strcmp(params->component, "fw.mgmt") == 0) {
1020+
priv.context.mode = PLDMFW_UPDATE_MODE_SINGLE_COMPONENT;
1021+
priv.context.component_identifier = NVM_COMP_ID_NVM;
1022+
} else if (params->component) {
1023+
return -EOPNOTSUPP;
1024+
}
1025+
10141026
/* the E822 device needs a slightly different ops */
10151027
if (hw->mac_type == ICE_MAC_GENERIC)
10161028
priv.context.ops = &ice_fwu_ops_e822;

drivers/net/ethernet/intel/ice/ice_lib.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1700,6 +1700,12 @@ bool ice_pf_state_is_nominal(struct ice_pf *pf)
17001700
return true;
17011701
}
17021702

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+
17031709
/**
17041710
* ice_update_eth_stats - Update VSI-specific ethernet statistics counters
17051711
* @vsi: the VSI to be updated

drivers/net/ethernet/intel/ice/ice_lib.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ void ice_set_q_vector_intrl(struct ice_q_vector *q_vector);
9090

9191
bool ice_is_safe_mode(struct ice_pf *pf);
9292
bool ice_is_rdma_ena(struct ice_pf *pf);
93+
bool ice_is_recovery_mode(struct ice_hw *hw);
9394
bool ice_is_dflt_vsi_in_use(struct ice_port_info *pi);
9495
bool ice_is_vsi_dflt_vsi(struct ice_vsi *vsi);
9596
int ice_set_dflt_vsi(struct ice_vsi *vsi);

drivers/net/ethernet/intel/ice/ice_main.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2364,6 +2364,18 @@ static void ice_check_media_subtask(struct ice_pf *pf)
23642364
}
23652365
}
23662366

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+
23672379
/**
23682380
* ice_service_task - manage and run subtasks
23692381
* @work: pointer to work_struct contained by the PF struct
@@ -5217,6 +5229,36 @@ void ice_unload(struct ice_pf *pf)
52175229
ice_decfg_netdev(vsi);
52185230
}
52195231

5232+
static int ice_probe_recovery_mode(struct ice_pf *pf)
5233+
{
5234+
struct device *dev = ice_pf_to_dev(pf);
5235+
int err;
5236+
5237+
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");
5238+
5239+
INIT_HLIST_HEAD(&pf->aq_wait_list);
5240+
spin_lock_init(&pf->aq_wait_lock);
5241+
init_waitqueue_head(&pf->aq_wait_queue);
5242+
5243+
timer_setup(&pf->serv_tmr, ice_service_timer, 0);
5244+
pf->serv_tmr_period = HZ;
5245+
INIT_WORK(&pf->serv_task, ice_service_task_recovery_mode);
5246+
clear_bit(ICE_SERVICE_SCHED, pf->state);
5247+
err = ice_create_all_ctrlq(&pf->hw);
5248+
if (err)
5249+
return err;
5250+
5251+
scoped_guard(devl, priv_to_devlink(pf)) {
5252+
err = ice_init_devlink(pf);
5253+
if (err)
5254+
return err;
5255+
}
5256+
5257+
ice_service_task_restart(pf);
5258+
5259+
return 0;
5260+
}
5261+
52205262
/**
52215263
* ice_probe - Device initialization routine
52225264
* @pdev: PCI device information struct
@@ -5308,6 +5350,9 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
53085350
hw->debug_mask = debug;
53095351
#endif
53105352

5353+
if (ice_is_recovery_mode(hw))
5354+
return ice_probe_recovery_mode(pf);
5355+
53115356
err = ice_init_hw(hw);
53125357
if (err) {
53135358
dev_err(dev, "ice_init_hw failed: %d\n", err);
@@ -5425,6 +5470,14 @@ static void ice_remove(struct pci_dev *pdev)
54255470
msleep(100);
54265471
}
54275472

5473+
if (ice_is_recovery_mode(&pf->hw)) {
5474+
ice_service_task_stop(pf);
5475+
scoped_guard(devl, priv_to_devlink(pf)) {
5476+
ice_deinit_devlink(pf);
5477+
}
5478+
return;
5479+
}
5480+
54285481
if (test_bit(ICE_FLAG_SRIOV_ENA, pf->flags)) {
54295482
set_bit(ICE_VF_RESETS_DISABLED, pf->state);
54305483
ice_free_vfs(pf);

include/linux/pldmfw.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,17 @@ struct pldmfw_ops;
125125
* a pointer to their own data, used to implement the device specific
126126
* operations.
127127
*/
128+
129+
enum pldmfw_update_mode {
130+
PLDMFW_UPDATE_MODE_FULL,
131+
PLDMFW_UPDATE_MODE_SINGLE_COMPONENT,
132+
};
133+
128134
struct pldmfw {
129135
const struct pldmfw_ops *ops;
130136
struct device *dev;
137+
u16 component_identifier;
138+
enum pldmfw_update_mode mode;
131139
};
132140

133141
bool pldmfw_op_pci_match_record(struct pldmfw *context, struct pldmfw_record *record);

include/net/devlink.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,6 +1535,7 @@ int devl_trylock(struct devlink *devlink);
15351535
void devl_unlock(struct devlink *devlink);
15361536
void devl_assert_locked(struct devlink *devlink);
15371537
bool devl_lock_is_held(struct devlink *devlink);
1538+
DEFINE_GUARD(devl, struct devlink *, devl_lock(_T), devl_unlock(_T));
15381539

15391540
struct ib_device;
15401541

lib/pldmfw/pldmfw.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,9 +481,17 @@ static int pldm_parse_components(struct pldmfw_priv *data)
481481
component->component_data = data->fw->data + offset;
482482
component->component_size = size;
483483

484+
if (data->context->mode == PLDMFW_UPDATE_MODE_SINGLE_COMPONENT &&
485+
data->context->component_identifier != component->identifier)
486+
continue;
487+
484488
list_add_tail(&component->entry, &data->components);
485489
}
486490

491+
if (data->context->mode == PLDMFW_UPDATE_MODE_SINGLE_COMPONENT &&
492+
list_empty(&data->components))
493+
return -ENOENT;
494+
487495
header_crc_ptr = data->fw->data + data->offset;
488496

489497
err = pldm_move_fw_offset(data, sizeof(data->header_crc));

0 commit comments

Comments
 (0)