On Wed, Jan 14, 2026 at 01:21:59PM +0000, Ciara Loftus wrote:
> The user may want to perform some actions before and/or after a VF
> reset, for example storing settings that may be lost during the reset
> and restoring them after the reset. To facilitate this, introduce two
> new functions which allow the user to register either a pre or post
> reset callback, which will be executed before or after the VF has been
> reset. To unregister the callback, simply use the register functions
> with a NULL callback and argument.
> 
> Signed-off-by: Ciara Loftus <[email protected]>
> ---
> v2:
> * Changed the function parameters of each cb
> * Created separate register functions for each type of cb
> * Use typedefs for the callbacks
> * Fixed some style issues
> * Permit NULL cb args when registering, application may just want to be
> notified of the event and not require further processing.
> ---
>  doc/guides/rel_notes/release_26_03.rst |  4 ++
>  drivers/net/intel/iavf/iavf.h          |  8 +++
>  drivers/net/intel/iavf/iavf_ethdev.c   | 80 ++++++++++++++++++++++++++
>  drivers/net/intel/iavf/rte_pmd_iavf.h  | 42 ++++++++++++++
>  4 files changed, 134 insertions(+)
> 
> diff --git a/doc/guides/rel_notes/release_26_03.rst 
> b/doc/guides/rel_notes/release_26_03.rst
> index 15dabee7a1..770f9933ee 100644
> --- a/doc/guides/rel_notes/release_26_03.rst
> +++ b/doc/guides/rel_notes/release_26_03.rst
> @@ -55,6 +55,10 @@ New Features
>       Also, make sure to start the actual text at the margin.
>       =======================================================
>  
> +* **Updated Intel iavf driver.**
> +
> +  * Added support for pre and post VF reset callbacks.
> +
>  
>  Removed Items
>  -------------
> diff --git a/drivers/net/intel/iavf/iavf.h b/drivers/net/intel/iavf/iavf.h
> index d78582e05c..50ca14e41c 100644
> --- a/drivers/net/intel/iavf/iavf.h
> +++ b/drivers/net/intel/iavf/iavf.h
> @@ -100,6 +100,10 @@ struct iavf_adapter;
>  struct ci_rx_queue;
>  struct ci_tx_queue;
>  
> +/** Callback function pointer for pre VF reset event */
> +typedef void (*iavf_pre_reset_cb_t)(uint16_t port_id, void *arg);
> +/** Callback function pointer for post VF reset event */
> +typedef void (*iavf_post_reset_cb_t)(uint16_t port_id, int reset_state, void 
> *arg);
>  
>  struct iavf_ipsec_crypto_stats {
>       uint64_t icount;
> @@ -257,6 +261,10 @@ struct iavf_info {
>  
>       struct iavf_vsi vsi;
>       bool vf_reset;  /* true for VF reset pending, false for no VF reset */
> +     iavf_pre_reset_cb_t pre_reset_cb; /* Pre reset callback function ptr */
> +     iavf_post_reset_cb_t post_reset_cb; /* Post reset callback function ptr 
> */
> +     void *pre_reset_cb_arg; /* Pre reset callback argument */
> +     void *post_reset_cb_arg; /* Post reset callback argument */
>       uint64_t flags;
>  
>       uint8_t *rss_lut;
> diff --git a/drivers/net/intel/iavf/iavf_ethdev.c 
> b/drivers/net/intel/iavf/iavf_ethdev.c
> index 15e49fe248..83e3486572 100644
> --- a/drivers/net/intel/iavf/iavf_ethdev.c
> +++ b/drivers/net/intel/iavf/iavf_ethdev.c
> @@ -3120,6 +3120,10 @@ iavf_handle_hw_reset(struct rte_eth_dev *dev, bool 
> vf_initiated_reset)
>       vf->in_reset_recovery = true;
>       iavf_set_no_poll(adapter, false);
>  
> +     /* Call the pre reset callback */
> +     if (vf->pre_reset_cb != NULL)
> +             vf->pre_reset_cb(dev->data->port_id, vf->pre_reset_cb_arg);
> +
>       ret = iavf_dev_reset(dev);
>       if (ret)
>               goto error;
> @@ -3144,6 +3148,10 @@ iavf_handle_hw_reset(struct rte_eth_dev *dev, bool 
> vf_initiated_reset)
>  error:
>       PMD_DRV_LOG(DEBUG, "RESET recover with error code=%dn", ret);
>  exit:
> +     /* Call the post reset callback */
> +     if (vf->post_reset_cb != NULL)
> +             vf->post_reset_cb(dev->data->port_id, ret, 
> vf->post_reset_cb_arg);
> +
>       vf->in_reset_recovery = false;
>       iavf_set_no_poll(adapter, false);
>  
> @@ -3183,6 +3191,78 @@ rte_pmd_iavf_reinit(uint16_t port)
>       return 0;
>  }
>  
> +static int
> +iavf_validate_reset_cb(uint16_t port, void *cb, void *cb_arg)
> +{
> +     struct rte_eth_dev *dev;
> +     struct iavf_info *vf;
> +
> +     RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
> +
> +     if (cb == NULL && cb_arg != NULL) {
> +             PMD_DRV_LOG(ERR, "Cannot unregister reset cb on port %u, arg 
> must be NULL.", port);
> +             return -EINVAL;
> +     }
> +
> +     dev = &rte_eth_devices[port];
> +     if (!is_iavf_supported(dev)) {
> +             PMD_DRV_LOG(ERR, "Cannot modify reset cb, port %u not an IAVF 
> device.", port);
> +             return -ENOTSUP;
> +     }
> +
> +     vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
> +     if (vf->in_reset_recovery) {
> +             PMD_DRV_LOG(ERR, "Cannot modify reset cb on port %u, VF is 
> resetting.", port);
> +             return -EBUSY;
> +     }
> +
> +     return 0;
> +}
> +
> +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_iavf_register_pre_reset_cb, 26.03)
> +int
> +rte_pmd_iavf_register_pre_reset_cb(uint16_t port,
> +                                iavf_pre_reset_cb_t pre_reset_cb,
> +                                void *pre_reset_cb_arg)
> +{
> +     struct rte_eth_dev *dev;
> +     struct iavf_info *vf;
> +     int ret;
> +
> +     ret = iavf_validate_reset_cb(port, pre_reset_cb, pre_reset_cb_arg);
> +     if (ret)
> +             return ret;
> +
> +     dev = &rte_eth_devices[port];
> +     vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
> +     vf->pre_reset_cb = pre_reset_cb;
> +     vf->pre_reset_cb_arg = pre_reset_cb_arg;
> +
> +     return 0;
> +}
> +
> +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_iavf_register_post_reset_cb, 26.03)
> +int
> +rte_pmd_iavf_register_post_reset_cb(uint16_t port,
> +                                 iavf_post_reset_cb_t post_reset_cb,
> +                                 void *post_reset_cb_arg)
> +{
> +     struct rte_eth_dev *dev;
> +     struct iavf_info *vf;
> +     int ret;
> +
> +     ret = iavf_validate_reset_cb(port, post_reset_cb, post_reset_cb_arg);
> +     if (ret)
> +             return ret;
> +
> +     dev = &rte_eth_devices[port];
> +     vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
> +     vf->post_reset_cb = post_reset_cb;
> +     vf->post_reset_cb_arg = post_reset_cb_arg;
> +
> +     return 0;
> +}
> +
>  void
>  iavf_set_no_poll(struct iavf_adapter *adapter, bool link_change)
>  {
> diff --git a/drivers/net/intel/iavf/rte_pmd_iavf.h 
> b/drivers/net/intel/iavf/rte_pmd_iavf.h
> index dea1bd2789..d13417eb08 100644
> --- a/drivers/net/intel/iavf/rte_pmd_iavf.h
> +++ b/drivers/net/intel/iavf/rte_pmd_iavf.h
> @@ -20,6 +20,8 @@
>  #include <rte_mbuf.h>
>  #include <rte_mbuf_dyn.h>
>  
> +#include "iavf.h"
> +
This include is an issue, because it's an exported i.e. installed, header
including a private header that will not be installed as part of DPDK. This
gets picked up by running chkincs from test-meson-builds.sh script. [I'm
surprised this wasn't caught in the CI].

I think you may need to invert the dependency, the private iavf.h can
instead depend on the public rte_pmd_iavf.h header file.

/Bruce

Reply via email to