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

Reply via email to