Originally, the iavf PMD does not perform special actions when it
receives a PF-to-VF reset event, resulting in vf being offline and
unavailable.

This patch enables vf auto-reset by setting 'watchdog_period' devargs
to true. The iavf PMD will perform an automatic reset to bring the vf
back online when it receives a PF-to-VF event.

v2: handling reset by event handler
v3: change reset process
v3: rebase

Signed-off-by: Shiyang He <shiyangx...@intel.com>
Signed-off-by: Liang-Min Larry Wang <liang-min.w...@intel.com>
---
 doc/guides/nics/intel_vf.rst           |  3 +
 doc/guides/rel_notes/release_23_11.rst |  3 +
 drivers/net/iavf/iavf.h                |  7 +++
 drivers/net/iavf/iavf_ethdev.c         | 86 +++++++++++++++++++++++---
 drivers/net/iavf/iavf_rxtx.c           | 52 ++++++++++------
 drivers/net/iavf/iavf_vchnl.c          | 11 +++-
 6 files changed, 135 insertions(+), 27 deletions(-)

diff --git a/doc/guides/nics/intel_vf.rst b/doc/guides/nics/intel_vf.rst
index d365dbc185..c0acd2a7f5 100644
--- a/doc/guides/nics/intel_vf.rst
+++ b/doc/guides/nics/intel_vf.rst
@@ -101,6 +101,9 @@ For more detail on SR-IOV, please refer to the following 
documents:
     Set ``devargs`` parameter ``watchdog_period`` to adjust the watchdog 
period in microseconds, or set it to 0 to disable the watchdog,
     for example, ``-a 18:01.0,watchdog_period=5000`` or ``-a 
18:01.0,watchdog_period=0``.
 
+    Enable vf auto-reset by setting the ``devargs`` parameter like ``-a 
18:01.0,enable_auto_reset=1`` when IAVF is backed
+    by an IntelĀ® E810 device or an IntelĀ® 700 Series Ethernet device.
+
 The PCIE host-interface of Intel Ethernet Switch FM10000 Series VF 
infrastructure
 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/doc/guides/rel_notes/release_23_11.rst 
b/doc/guides/rel_notes/release_23_11.rst
index 03191b3ae0..8536ce88f4 100644
--- a/doc/guides/rel_notes/release_23_11.rst
+++ b/doc/guides/rel_notes/release_23_11.rst
@@ -86,6 +86,9 @@ New Features
 
   * Added support for port representor.
 
+* **Updated Intel iavf driver.**
+  * Added support for iavf auto-reset.
+
 Removed Items
 -------------
 
diff --git a/drivers/net/iavf/iavf.h b/drivers/net/iavf/iavf.h
index 98861e4242..3641401f38 100644
--- a/drivers/net/iavf/iavf.h
+++ b/drivers/net/iavf/iavf.h
@@ -277,6 +277,8 @@ struct iavf_info {
 
        struct rte_eth_dev *eth_dev;
 
+       bool in_reset_recovery;
+
        uint32_t ptp_caps;
        rte_spinlock_t phc_time_aq_lock;
 };
@@ -305,6 +307,7 @@ struct iavf_devargs {
        uint8_t proto_xtr[IAVF_MAX_QUEUE_NUM];
        uint16_t quanta_size;
        uint32_t watchdog_period;
+       uint8_t  enable_auto_reset;
 };
 
 struct iavf_security_ctx;
@@ -426,6 +429,9 @@ _atomic_set_async_response_cmd(struct iavf_info *vf, enum 
virtchnl_ops ops)
 }
 int iavf_check_api_version(struct iavf_adapter *adapter);
 int iavf_get_vf_resource(struct iavf_adapter *adapter);
+void iavf_dev_event_post(struct rte_eth_dev *dev,
+               enum rte_eth_event_type event,
+               void *param, size_t param_alloc_size);
 void iavf_dev_event_handler_fini(void);
 int iavf_dev_event_handler_init(void);
 void iavf_handle_virtchnl_msg(struct rte_eth_dev *dev);
@@ -501,4 +507,5 @@ int iavf_flow_sub_check(struct iavf_adapter *adapter,
                        struct iavf_fsub_conf *filter);
 void iavf_dev_watchdog_enable(struct iavf_adapter *adapter);
 void iavf_dev_watchdog_disable(struct iavf_adapter *adapter);
+int iavf_handle_hw_reset(struct rte_eth_dev *dev);
 #endif /* _IAVF_ETHDEV_H_ */
diff --git a/drivers/net/iavf/iavf_ethdev.c b/drivers/net/iavf/iavf_ethdev.c
index 97390237ba..94b9881fce 100644
--- a/drivers/net/iavf/iavf_ethdev.c
+++ b/drivers/net/iavf/iavf_ethdev.c
@@ -37,6 +37,7 @@
 #define IAVF_PROTO_XTR_ARG         "proto_xtr"
 #define IAVF_QUANTA_SIZE_ARG       "quanta_size"
 #define IAVF_RESET_WATCHDOG_ARG    "watchdog_period"
+#define IAVF_ENABLE_AUTO_RESET_ARG "enable_auto_reset"
 
 uint64_t iavf_timestamp_dynflag;
 int iavf_timestamp_dynfield_offset = -1;
@@ -45,6 +46,7 @@ static const char * const iavf_valid_args[] = {
        IAVF_PROTO_XTR_ARG,
        IAVF_QUANTA_SIZE_ARG,
        IAVF_RESET_WATCHDOG_ARG,
+       IAVF_ENABLE_AUTO_RESET_ARG,
        NULL
 };
 
@@ -307,8 +309,8 @@ iavf_dev_watchdog(void *cb_arg)
                        adapter->vf.vf_reset = true;
                        adapter->vf.link_up = false;
 
-                       rte_eth_dev_callback_process(adapter->vf.eth_dev,
-                               RTE_ETH_EVENT_INTR_RESET, NULL);
+                       iavf_dev_event_post(adapter->vf.eth_dev, 
RTE_ETH_EVENT_INTR_RESET,
+                               NULL, 0);
                }
        }
 
@@ -1101,12 +1103,15 @@ iavf_dev_stop(struct rte_eth_dev *dev)
        /* Rx interrupt vector mapping free */
        rte_intr_vec_list_free(intr_handle);
 
-       /* remove all mac addrs */
-       iavf_add_del_all_mac_addr(adapter, false);
+       /* adminq will be disabled when vf is resetting. */
+       if (!vf->in_reset_recovery) {
+               /* remove all mac addrs */
+               iavf_add_del_all_mac_addr(adapter, false);
 
-       /* remove all multicast addresses */
-       iavf_add_del_mc_addr_list(adapter, vf->mc_addrs, vf->mc_addrs_num,
+               /* remove all multicast addresses */
+               iavf_add_del_mc_addr_list(adapter, vf->mc_addrs, 
vf->mc_addrs_num,
                                  false);
+       }
 
        iavf_stop_queues(dev);
 
@@ -2239,6 +2244,26 @@ parse_u16(__rte_unused const char *key, const char 
*value, void *args)
        return 0;
 }
 
+static int
+parse_bool(const char *key, const char *value, void *args)
+{
+       int *i = (int *)args;
+       char *end;
+       int num;
+
+       num = strtoul(value, &end, 10);
+
+       if (num != 0 && num != 1) {
+               PMD_DRV_LOG(WARNING, "invalid value:\"%s\" for key:\"%s\", "
+                       "value must be 0 or 1",
+                       value, key);
+               return -1;
+       }
+
+       *i = num;
+       return 0;
+}
+
 static int
 iavf_parse_watchdog_period(__rte_unused const char *key, const char *value, 
void *args)
 {
@@ -2307,6 +2332,11 @@ static int iavf_parse_devargs(struct rte_eth_dev *dev)
                goto bail;
        }
 
+       ret = rte_kvargs_process(kvlist, IAVF_ENABLE_AUTO_RESET_ARG,
+                                &parse_bool, &ad->devargs.enable_auto_reset);
+       if (ret)
+               goto bail;
+
 bail:
        rte_kvargs_free(kvlist);
        return ret;
@@ -2887,12 +2917,15 @@ iavf_dev_close(struct rte_eth_dev *dev)
 static int
 iavf_dev_uninit(struct rte_eth_dev *dev)
 {
+       struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+
        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
                return -EPERM;
 
        iavf_dev_close(dev);
 
-       iavf_dev_event_handler_fini();
+       if (!vf->in_reset_recovery)
+               iavf_dev_event_handler_fini();
 
        return 0;
 }
@@ -2905,6 +2938,7 @@ iavf_dev_reset(struct rte_eth_dev *dev)
 {
        int ret;
        struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 
        /*
         * Check whether the VF reset has been done and inform application,
@@ -2916,6 +2950,7 @@ iavf_dev_reset(struct rte_eth_dev *dev)
                PMD_DRV_LOG(ERR, "Wait too long for reset done!\n");
                return ret;
        }
+       vf->vf_reset = false;
 
        PMD_DRV_LOG(DEBUG, "Start dev_reset ...\n");
        ret = iavf_dev_uninit(dev);
@@ -2925,6 +2960,43 @@ iavf_dev_reset(struct rte_eth_dev *dev)
        return iavf_dev_init(dev);
 }
 
+/*
+ * Handle hardware reset
+ */
+int
+iavf_handle_hw_reset(struct rte_eth_dev *dev)
+{
+       struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+       int ret;
+
+       vf->in_reset_recovery = true;
+
+       ret = iavf_dev_reset(dev);
+       if (ret)
+               goto error;
+
+       /* VF states restore */
+       ret = iavf_dev_configure(dev);
+       if (ret)
+               goto error;
+
+       iavf_dev_xstats_reset(dev);
+
+       /* start the device */
+       ret = iavf_dev_start(dev);
+       if (ret)
+               goto error;
+       dev->data->dev_started = 1;
+
+       vf->in_reset_recovery = false;
+       return 0;
+
+error:
+       PMD_DRV_LOG(DEBUG, "RESET recover with error code=%d\n", ret);
+       vf->in_reset_recovery = false;
+       return ret;
+}
+
 static int
 iavf_dcf_cap_check_handler(__rte_unused const char *key,
                           const char *value, __rte_unused void *opaque)
diff --git a/drivers/net/iavf/iavf_rxtx.c b/drivers/net/iavf/iavf_rxtx.c
index 72e8ae8aa6..0484988d13 100644
--- a/drivers/net/iavf/iavf_rxtx.c
+++ b/drivers/net/iavf/iavf_rxtx.c
@@ -1101,15 +1101,44 @@ iavf_dev_tx_queue_release(struct rte_eth_dev *dev, 
uint16_t qid)
        rte_free(q);
 }
 
+static void
+iavf_reset_queues(struct rte_eth_dev *dev)
+{
+       struct iavf_rx_queue *rxq;
+       struct iavf_tx_queue *txq;
+       int i;
+
+       for (i = 0; i < dev->data->nb_tx_queues; i++) {
+               txq = dev->data->tx_queues[i];
+               if (!txq)
+                       continue;
+               
iavf_txq_release_mbufs_ops[txq->rel_mbufs_type].release_mbufs(txq);
+               reset_tx_queue(txq);
+               dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
+       }
+       for (i = 0; i < dev->data->nb_rx_queues; i++) {
+               rxq = dev->data->rx_queues[i];
+               if (!rxq)
+                       continue;
+               
iavf_rxq_release_mbufs_ops[rxq->rel_mbufs_type].release_mbufs(rxq);
+               reset_rx_queue(rxq);
+               dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
+       }
+}
+
 void
 iavf_stop_queues(struct rte_eth_dev *dev)
 {
        struct iavf_adapter *adapter =
                IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
-       struct iavf_rx_queue *rxq;
-       struct iavf_tx_queue *txq;
-       int ret, i;
+       int ret;
+
+       /* adminq will be disabled when vf is resetting. */
+       if (vf->in_reset_recovery) {
+               iavf_reset_queues(dev);
+               return;
+       }
 
        /* Stop All queues */
        if (!vf->lv_enabled) {
@@ -1125,22 +1154,7 @@ iavf_stop_queues(struct rte_eth_dev *dev)
        if (ret)
                PMD_DRV_LOG(WARNING, "Fail to stop queues");
 
-       for (i = 0; i < dev->data->nb_tx_queues; i++) {
-               txq = dev->data->tx_queues[i];
-               if (!txq)
-                       continue;
-               
iavf_txq_release_mbufs_ops[txq->rel_mbufs_type].release_mbufs(txq);
-               reset_tx_queue(txq);
-               dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
-       }
-       for (i = 0; i < dev->data->nb_rx_queues; i++) {
-               rxq = dev->data->rx_queues[i];
-               if (!rxq)
-                       continue;
-               
iavf_rxq_release_mbufs_ops[rxq->rel_mbufs_type].release_mbufs(rxq);
-               reset_rx_queue(rxq);
-               dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
-       }
+       iavf_reset_queues(dev);
 }
 
 #define IAVF_RX_FLEX_ERR0_BITS \
diff --git a/drivers/net/iavf/iavf_vchnl.c b/drivers/net/iavf/iavf_vchnl.c
index b3e106b41f..caf7cd6d8e 100644
--- a/drivers/net/iavf/iavf_vchnl.c
+++ b/drivers/net/iavf/iavf_vchnl.c
@@ -79,6 +79,15 @@ iavf_dev_event_handle(void *param __rte_unused)
                struct iavf_event_element *pos, *save_next;
                TAILQ_FOREACH_SAFE(pos, &pending, next, save_next) {
                        TAILQ_REMOVE(&pending, pos, next);
+
+                       struct iavf_adapter *adapter = 
pos->dev->data->dev_private;
+                       if (pos->event == RTE_ETH_EVENT_INTR_RESET &&
+                           adapter->devargs.enable_auto_reset) {
+                               iavf_handle_hw_reset(pos->dev);
+                               rte_free(pos);
+                               continue;
+                       }
+
                        rte_eth_dev_callback_process(pos->dev, pos->event, 
pos->param);
                        rte_free(pos);
                }
@@ -87,7 +96,7 @@ iavf_dev_event_handle(void *param __rte_unused)
        return 0;
 }
 
-static void
+void
 iavf_dev_event_post(struct rte_eth_dev *dev,
                enum rte_eth_event_type event,
                void *param, size_t param_alloc_size)
-- 
2.37.2

Reply via email to