* [patch 1/2] ice: Use ICE_FW_RECOVERY_MODE state to track recovery mode
2026-05-22 14:22 [patch 0/2] ice: Handle nits in physical card removal Cyrill Gorcunov
@ 2026-05-22 14:22 ` Cyrill Gorcunov
2026-05-22 14:22 ` [patch 2/2] ice: Fix wrong dsn read in ice_adapter_put Cyrill Gorcunov
1 sibling, 0 replies; 3+ messages in thread
From: Cyrill Gorcunov @ 2026-05-22 14:22 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: Simon Horman, anthony.l.nguyen, przemyslaw.kitszel,
Cyrill Gorcunov
If card is in recovery mode and we remove it physically then during
ice_remove() we read device register to fetch its state again which
is wrong since the device is no longer present. Fix it marking the
device state with ICE_FW_RECOVERY_MODE bit.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
---
drivers/net/ethernet/intel/ice/ice.h | 1 +
drivers/net/ethernet/intel/ice/ice_main.c | 9 ++++++++-
2 files changed, 9 insertions(+), 1 deletion(-)
Index: linux-tip.git/drivers/net/ethernet/intel/ice/ice.h
===================================================================
--- linux-tip.git.orig/drivers/net/ethernet/intel/ice/ice.h
+++ linux-tip.git/drivers/net/ethernet/intel/ice/ice.h
@@ -310,6 +310,7 @@ enum ice_pf_state {
ICE_PHY_INIT_COMPLETE,
ICE_FD_VF_FLUSH_CTX, /* set at FD Rx IRQ or timeout */
ICE_AUX_ERR_PENDING,
+ ICE_FW_RECOVERY_MODE, /* Firmware in recovery mode */
ICE_STATE_NBITS /* must be last */
};
Index: linux-tip.git/drivers/net/ethernet/intel/ice/ice_main.c
===================================================================
--- linux-tip.git.orig/drivers/net/ethernet/intel/ice/ice_main.c
+++ linux-tip.git/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5121,6 +5121,8 @@ static int ice_probe_recovery_mode(struc
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");
+ set_bit(ICE_FW_RECOVERY_MODE, pf->state);
+
INIT_HLIST_HEAD(&pf->aq_wait_list);
spin_lock_init(&pf->aq_wait_lock);
init_waitqueue_head(&pf->aq_wait_queue);
@@ -5366,7 +5368,12 @@ static void ice_remove(struct pci_dev *p
msleep(100);
}
- if (ice_is_recovery_mode(&pf->hw)) {
+ /*
+ * .remove() may be called when adapter is physically
+ * unplugged so we can't read the fw state but use
+ * the flag instead.
+ */
+ if (test_bit(ICE_FW_RECOVERY_MODE, pf->state)) {
ice_service_task_stop(pf);
scoped_guard(devl, priv_to_devlink(pf)) {
ice_deinit_devlink(pf);
^ permalink raw reply [flat|nested] 3+ messages in thread* [patch 2/2] ice: Fix wrong dsn read in ice_adapter_put
2026-05-22 14:22 [patch 0/2] ice: Handle nits in physical card removal Cyrill Gorcunov
2026-05-22 14:22 ` [patch 1/2] ice: Use ICE_FW_RECOVERY_MODE state to track recovery mode Cyrill Gorcunov
@ 2026-05-22 14:22 ` Cyrill Gorcunov
1 sibling, 0 replies; 3+ messages in thread
From: Cyrill Gorcunov @ 2026-05-22 14:22 UTC (permalink / raw)
To: linux-kernel, netdev
Cc: Simon Horman, anthony.l.nguyen, przemyslaw.kitszel,
Cyrill Gorcunov
When registering an adapter instance, we read the PCI configuration
space to fetch the DSN and generate an adapter index for lookups.
However, if the adapter has been physically unplugged, the PCI space
is no longer accessible. Reading it returns a zero value, which results
in either an incorrect adapter instance being put or the proper instance
not being put at all. To fix this, we will use the previously known
index instead.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
---
drivers/net/ethernet/intel/ice/ice_adapter.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
Index: linux-tip.git/drivers/net/ethernet/intel/ice/ice_adapter.c
===================================================================
--- linux-tip.git.orig/drivers/net/ethernet/intel/ice/ice_adapter.c
+++ linux-tip.git/drivers/net/ethernet/intel/ice/ice_adapter.c
@@ -40,10 +40,8 @@ static u64 ice_adapter_index(struct pci_
}
}
-static unsigned long ice_adapter_xa_index(struct pci_dev *pdev)
+static unsigned long xa_index_mangle(u64 index)
{
- u64 index = ice_adapter_index(pdev);
-
#if BITS_PER_LONG == 64
return index;
#else
@@ -51,6 +49,11 @@ static unsigned long ice_adapter_xa_inde
#endif
}
+static unsigned long ice_adapter_xa_index(struct pci_dev *pdev)
+{
+ return xa_index_mangle(ice_adapter_index(pdev));
+}
+
static struct ice_adapter *ice_adapter_new(struct pci_dev *pdev)
{
struct ice_adapter *adapter;
@@ -130,13 +133,17 @@ struct ice_adapter *ice_adapter_get(stru
*/
void ice_adapter_put(struct pci_dev *pdev)
{
+ const struct ice_pf *pf = pci_get_drvdata(pdev);
struct ice_adapter *adapter;
unsigned long index;
- index = ice_adapter_xa_index(pdev);
+ if (WARN_ON(!pf->adapter))
+ return;
+
scoped_guard(mutex, &ice_adapters_mutex) {
+ index = xa_index_mangle(pf->adapter->index);
adapter = xa_load(&ice_adapters, index);
- if (WARN_ON(!adapter))
+ if (WARN_ON(!adapter || adapter != pf->adapter))
return;
if (!refcount_dec_and_test(&adapter->refcount))
return;
^ permalink raw reply [flat|nested] 3+ messages in thread