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 <[email protected]> --- 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

