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 a new function which allows 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 same function with a null callback as argument.
Signed-off-by: Ciara Loftus <[email protected]> --- doc/guides/rel_notes/release_26_03.rst | 4 ++ drivers/net/intel/iavf/iavf.h | 15 +++++++ drivers/net/intel/iavf/iavf_ethdev.c | 62 ++++++++++++++++++++++++++ drivers/net/intel/iavf/rte_pmd_iavf.h | 24 ++++++++++ 4 files changed, 105 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..5482472549 100644 --- a/drivers/net/intel/iavf/iavf.h +++ b/drivers/net/intel/iavf/iavf.h @@ -224,6 +224,17 @@ struct iavf_qtc_map { uint16_t queue_count; }; +enum iavf_reset_cb_type { + IAVF_RESET_CB_TYPE_PRE, + IAVF_RESET_CB_TYPE_POST, +}; + +struct iavf_reset_cb_arg { + uint16_t port_id; + int reset_status; + void *user_state; +}; + /* Structure to store private data specific for VF instance. */ struct iavf_info { uint16_t num_queue_pairs; @@ -257,6 +268,10 @@ struct iavf_info { struct iavf_vsi vsi; bool vf_reset; /* true for VF reset pending, false for no VF reset */ + void (*pre_reset_cb)(struct iavf_reset_cb_arg *arg); /* Pre reset callback function ptr */ + void (*post_reset_cb)(struct iavf_reset_cb_arg *arg); /* Post reset callback function ptr */ + struct iavf_reset_cb_arg *pre_reset_cb_arg; /* Pre reset function argument */ + struct iavf_reset_cb_arg *post_reset_cb_arg; /* Post reset function 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..553f38a286 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) + (*vf->pre_reset_cb)(vf->pre_reset_cb_arg); + ret = iavf_dev_reset(dev); if (ret) goto error; @@ -3144,6 +3148,13 @@ 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: + /* Update the reset status */ + if (vf->post_reset_cb_arg) + vf->post_reset_cb_arg->reset_status = ret; + /* Call the post reset callback */ + if (vf->post_reset_cb) + (*vf->post_reset_cb)(vf->post_reset_cb_arg); + vf->in_reset_recovery = false; iavf_set_no_poll(adapter, false); @@ -3183,6 +3194,57 @@ rte_pmd_iavf_reinit(uint16_t port) return 0; } +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_pmd_iavf_reset_cb_register, 26.03) +int +rte_pmd_iavf_reset_cb_register(uint16_t port, + enum iavf_reset_cb_type cb_type, + void (*reset_cb)(struct iavf_reset_cb_arg *arg), + struct iavf_reset_cb_arg *reset_arg) +{ + struct rte_eth_dev *dev; + struct iavf_info *vf; + + RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV); + + dev = &rte_eth_devices[port]; + + if (!is_iavf_supported(dev)) { + PMD_DRV_LOG(ERR, "Cannot register callback, port %u is not an IAVF device.", port); + return -ENOTSUP; + } + + if (reset_cb != NULL && reset_arg == NULL) { + PMD_DRV_LOG(ERR, "Cannot register callback on port %u, arg is NULL.", port); + return -EINVAL; + } + + if (reset_arg != NULL) + reset_arg->port_id = port; + + vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private); + + if (vf->in_reset_recovery) { + PMD_DRV_LOG(ERR, "Cannot modify reset callback on port %u, VF is resetting.", port); + return -EBUSY; + } + + switch (cb_type) { + case IAVF_RESET_CB_TYPE_PRE: + vf->pre_reset_cb = reset_cb; + vf->pre_reset_cb_arg = reset_arg; + break; + case IAVF_RESET_CB_TYPE_POST: + vf->post_reset_cb = reset_cb; + vf->post_reset_cb_arg = reset_arg; + break; + default: + PMD_DRV_LOG(ERR, "Invalid reset callback type: %d", cb_type); + return -EINVAL; + } + + 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..365f8a3e6a 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,28 @@ 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 or post reset event callback + * + * @param port + * The port identifier of the Ethernet device. + * @param cb_type + * The callback type, pre-reset (0) or post-reset (1). + * @param reset_cb + * The callback function that will be invoked by the driver. + * Pass NULL to unregister an existing callback. + * @param reset_arg + * The argument passed to the callback function. + * Can be NULL when unregistering (reset_cb is NULL). + * @return + * 0 if successful, otherwise if a failure occurs. + */ +__rte_experimental +int rte_pmd_iavf_reset_cb_register(uint16_t port, + enum iavf_reset_cb_type cb_type, + void (*reset_cb)(struct iavf_reset_cb_arg *arg), + struct iavf_reset_cb_arg *reset_arg); + /** * The mbuf dynamic field pointer for flexible descriptor's extraction metadata. */ -- 2.43.0

