[RFC 2/2] net/iavf: restore promiscuous mode only after VF reset
Ciara Loftus
ciara.loftus at intel.com
Tue Jul 21 15:08:14 CEST 2026
The promiscuous and all-multicast settings persist in hardware across
a port stop/start and are only cleared by a VF reset. Despite this,
the ethdev start path re-applied them on every `dev_start` through the
config restore logic. Together with the driver's own restore after a
reset, a reset followed by a start reprogrammed them twice and issued
redundant requests to the PF.
Implement the `get_restore_flags` callback to clear
`RTE_ETH_RESTORE_PROMISC` and `RTE_ETH_RESTORE_ALLMULTI` so ethdev
skips them on start; the driver restores them only after a VF reset.
A queue reconfiguration in `iavf_dev_configure` also triggers a reset,
so the states are re-applied there too, except during reset recovery
where the reset handler already restores them once.
Signed-off-by: Ciara Loftus <ciara.loftus at intel.com>
---
drivers/net/intel/iavf/iavf_ethdev.c | 34 ++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/drivers/net/intel/iavf/iavf_ethdev.c b/drivers/net/intel/iavf/iavf_ethdev.c
index 829573983a..183d986831 100644
--- a/drivers/net/intel/iavf/iavf_ethdev.c
+++ b/drivers/net/intel/iavf/iavf_ethdev.c
@@ -163,6 +163,9 @@ static int iavf_set_mc_addr_list(struct rte_eth_dev *dev,
struct rte_ether_addr *mc_addrs,
uint32_t mc_addrs_num);
static int iavf_tm_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg);
+static uint64_t iavf_get_restore_flags(struct rte_eth_dev *dev,
+ enum rte_eth_dev_operation op);
+static int iavf_post_reset_reconfig(struct rte_eth_dev *dev);
static const struct rte_pci_id pci_id_iavf_map[] = {
{ RTE_PCI_DEVICE(IAVF_INTEL_VENDOR_ID, IAVF_DEV_ID_ADAPTIVE_VF) },
@@ -262,6 +265,7 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {
.tx_done_cleanup = iavf_dev_tx_done_cleanup,
.get_monitor_addr = iavf_get_monitor_addr,
.tm_ops_get = iavf_tm_ops_get,
+ .get_restore_flags = iavf_get_restore_flags,
};
static int
@@ -282,6 +286,19 @@ iavf_tm_ops_get(struct rte_eth_dev *dev,
return 0;
}
+static uint64_t
+iavf_get_restore_flags(__rte_unused struct rte_eth_dev *dev,
+ __rte_unused enum rte_eth_dev_operation op)
+{
+ /*
+ * The unicast and multicast promiscuous settings persist across a
+ * stop/start; they are only cleared by a VF reset, which the driver
+ * restores itself. So ethdev does not need to restore them on start.
+ */
+ return RTE_ETH_RESTORE_ALL & ~(RTE_ETH_RESTORE_PROMISC |
+ RTE_ETH_RESTORE_ALLMULTI);
+}
+
__rte_unused
static int
iavf_vfr_inprogress(struct iavf_hw *hw)
@@ -673,6 +690,7 @@ iavf_dev_configure(struct rte_eth_dev *dev)
struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
uint16_t num_queue_pairs = RTE_MAX(dev->data->nb_rx_queues,
dev->data->nb_tx_queues);
+ bool reset_done = false;
int ret;
if (ad->closed)
@@ -702,6 +720,7 @@ iavf_dev_configure(struct rte_eth_dev *dev)
ret = iavf_queues_req_reset(dev, num_queue_pairs);
if (ret)
return ret;
+ reset_done = true;
ret = iavf_get_max_rss_queue_region(ad);
if (ret) {
@@ -720,6 +739,7 @@ iavf_dev_configure(struct rte_eth_dev *dev)
ret = iavf_queues_req_reset(dev, num_queue_pairs);
if (ret)
return ret;
+ reset_done = true;
vf->lv_enabled = false;
}
@@ -735,6 +755,20 @@ iavf_dev_configure(struct rte_eth_dev *dev)
return -1;
}
}
+
+ /*
+ * A queue reconfiguration above triggers a VF reset, which clears the
+ * promiscuous and all-multicast settings in hardware. Re-apply the
+ * pre-reset states here, unless this configure is itself part of reset
+ * recovery, in which case the reset handler restores them once at the
+ * end (avoiding a double restore).
+ */
+ if (reset_done && !vf->in_reset_recovery) {
+ ret = iavf_post_reset_reconfig(dev);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
--
2.43.0
More information about the dev
mailing list