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" + #ifdef __cplusplus extern "C" { #endif @@ -109,6 +111,46 @@ extern uint64_t rte_pmd_ifd_dynflag_proto_xtr_ipsec_crypto_said_mask; __rte_experimental int rte_pmd_iavf_reinit(uint16_t port); +/** + * Register or unregister a pre reset event callback + * + * @param port + * The port identifier of the Ethernet device. + * @param pre_reset_cb + * The callback function that will be invoked by the driver prior to a reset. + * Pass NULL to unregister an existing callback. + * @param pre_reset_cb_arg + * The argument passed to the callback function. + * May be NULL when registering the callback if no argument is needed to the callback. + * Must be NULL when unregistering the callback. + * @return + * 0 if successful, otherwise if a failure occurs. + */ +__rte_experimental +int rte_pmd_iavf_register_pre_reset_cb(uint16_t port, + iavf_pre_reset_cb_t pre_reset_cb, + void *pre_reset_cb_arg); + +/** + * Register or unregister a post reset event callback + * + * @param port + * The port identifier of the Ethernet device. + * @param post_reset_cb + * The callback function that will be invoked by the driver after a reset. + * Pass NULL to unregister an existing callback. + * @param post_reset_cb_arg + * The argument passed to the callback function. + * May be NULL when registering the callback if no argument is needed to the callback. + * Must be NULL when unregistering the callback. + * @return + * 0 if successful, otherwise if a failure occurs. + */ +__rte_experimental +int rte_pmd_iavf_register_post_reset_cb(uint16_t port, + iavf_post_reset_cb_t post_reset_cb, + void *post_reset_cb_arg); + /** * The mbuf dynamic field pointer for flexible descriptor's extraction metadata. */ -- 2.43.0

