From: Shiyang He <shiyangx.he@intel.com>
To: dev@dpdk.org
Cc: yidingx.zhou@intel.com, Shiyang He <shiyangx.he@intel.com>,
Simei Su <simei.su@intel.com>, Wenjun Wu <wenjun1.wu@intel.com>,
Qiming Yang <qiming.yang@intel.com>,
Yuying Zhang <Yuying.Zhang@intel.com>,
Beilei Xing <beilei.xing@intel.com>,
Jingjing Wu <jingjing.wu@intel.com>
Subject: [PATCH] net/iavf: add devargs to enable vf auto-reset
Date: Tue, 1 Aug 2023 09:48:14 +0000 [thread overview]
Message-ID: <20230801094815.4028257-1-shiyangx.he@intel.com> (raw)
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.
Signed-off-by: Shiyang He <shiyangx.he@intel.com>
---
doc/guides/nics/intel_vf.rst | 3 +
drivers/net/iavf/iavf.h | 28 ++++++
drivers/net/iavf/iavf_ethdev.c | 166 +++++++++++++++++++++++++++++++++
drivers/net/iavf/iavf_rxtx.c | 25 +++++
drivers/net/iavf/iavf_rxtx.h | 1 +
drivers/net/iavf/iavf_vchnl.c | 8 ++
6 files changed, 231 insertions(+)
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/drivers/net/iavf/iavf.h b/drivers/net/iavf/iavf.h
index 98861e4242..a150b7d5cf 100644
--- a/drivers/net/iavf/iavf.h
+++ b/drivers/net/iavf/iavf.h
@@ -95,6 +95,24 @@
#define IAVF_L2TPV2_FLAGS_LEN 0x4000
+#ifndef DIV_ROUND_UP
+#define DIV_ROUND_UP(n, d) ( \
+{ \
+ const typeof(d) __d = d; \
+ (((n) + (__d) - 1) / (__d));\
+} \
+)
+#endif
+#ifndef DELAY
+#define DELAY(x) rte_delay_us(x)
+#endif
+#ifndef msleep
+#define msleep(x) DELAY(1000 * (x))
+#endif
+#ifndef usleep_range
+#define usleep_range(min, max) msleep(DIV_ROUND_UP(min, 1000))
+#endif
+
struct iavf_adapter;
struct iavf_rx_queue;
struct iavf_tx_queue;
@@ -305,6 +323,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;
@@ -424,6 +443,14 @@ _atomic_set_async_response_cmd(struct iavf_info *vf, enum virtchnl_ops ops)
return !ret;
}
+
+static inline bool
+iavf_is_reset(struct iavf_hw *hw)
+{
+ return !(IAVF_READ_REG(hw, IAVF_VF_ARQLEN1) &
+ IAVF_VF_ARQLEN1_ARQENABLE_MASK);
+}
+
int iavf_check_api_version(struct iavf_adapter *adapter);
int iavf_get_vf_resource(struct iavf_adapter *adapter);
void iavf_dev_event_handler_fini(void);
@@ -501,4 +528,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 f2fc5a5621..5f9fce34a5 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
};
@@ -305,6 +307,8 @@ iavf_dev_watchdog(void *cb_arg)
adapter->vf.vf_reset = true;
adapter->vf.link_up = false;
+ iavf_handle_hw_reset(adapter->vf.eth_dev);
+
rte_eth_dev_callback_process(adapter->vf.eth_dev,
RTE_ETH_EVENT_INTR_RESET, NULL);
}
@@ -2210,6 +2214,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)
{
@@ -2278,6 +2302,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;
@@ -2879,6 +2908,143 @@ iavf_dev_reset(struct rte_eth_dev *dev)
return iavf_dev_init(dev);
}
+static bool
+iavf_is_reset_detected(struct iavf_adapter *adapter)
+{
+ struct iavf_hw *hw = &adapter->hw;
+ int i;
+
+ /* poll until we see the reset actually happen */
+ for (i = 0; i < IAVF_RESET_WAIT_CNT; i++) {
+ if (iavf_is_reset(hw))
+ return true;
+ usleep_range(5000, 10000);
+ }
+
+ return false;
+}
+
+static int
+iavf_uninit_hw(struct rte_eth_dev *dev, struct iavf_hw *hw)
+{
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+ struct rte_intr_handle *intr_handle = dev->intr_handle;
+ struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+ struct iavf_adapter *adapter = dev->data->dev_private;
+
+ iavf_reset_queues(dev);
+
+ /* Disable the interrupt for Rx */
+ rte_intr_efd_disable(intr_handle);
+ /* Rx interrupt vector mapping free */
+ rte_intr_vec_list_free(intr_handle);
+
+ adapter->stopped = 1;
+ dev->data->dev_started = 0;
+
+ adapter->closed = true;
+
+ /* free iAVF security device context all related resources */
+ iavf_security_ctx_destroy(adapter);
+
+ iavf_flow_flush(dev, NULL);
+ iavf_flow_uninit(adapter);
+
+ if (vf->promisc_unicast_enabled || vf->promisc_multicast_enabled)
+ iavf_config_promisc(adapter, false, false);
+
+ iavf_shutdown_adminq(hw);
+ if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) {
+ /* disable uio intr before callback unregister */
+ rte_intr_disable(intr_handle);
+
+ /* unregister callback func from eal lib */
+ rte_intr_callback_unregister(intr_handle,
+ iavf_dev_interrupt_handler, dev);
+ }
+ iavf_disable_irq0(hw);
+
+ if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_QOS)
+ iavf_tm_conf_uninit(dev);
+
+ if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF) {
+ if (vf->rss_lut) {
+ rte_free(vf->rss_lut);
+ vf->rss_lut = NULL;
+ }
+ if (vf->rss_key) {
+ rte_free(vf->rss_key);
+ vf->rss_key = NULL;
+ }
+ }
+
+ rte_free(vf->vf_res);
+ vf->vsi_res = NULL;
+ vf->vf_res = NULL;
+
+ rte_free(vf->aq_resp);
+ vf->aq_resp = NULL;
+
+ if (vf->vf_reset && !rte_pci_set_bus_master(pci_dev, true))
+ vf->vf_reset = false;
+
+ /* disable watchdog */
+ iavf_dev_watchdog_disable(adapter);
+
+ return 0;
+}
+
+static int
+iavf_reset_hw(struct rte_eth_dev *dev, struct iavf_hw *hw)
+{
+ iavf_uninit_hw(dev, hw);
+
+ return iavf_dev_init(dev);
+}
+
+/*
+ * Handle hardware reset
+ */
+int
+iavf_handle_hw_reset(struct rte_eth_dev *dev)
+{
+ struct iavf_adapter *adapter = dev->data->dev_private;
+ 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);
+ int ret;
+
+ if (!adapter->devargs.enable_auto_reset)
+ return 0;
+
+ if (!iavf_is_reset_detected(adapter))
+ return 0;
+
+ if (iavf_reset_hw(dev, hw))
+ return -1;
+
+ /*
+ * This may return a failure due to the vf may not able to get
+ * a response from the pf.
+ */
+ ret = iavf_dev_configure(dev);
+ if (ret)
+ PMD_DRV_LOG(ERR, "Failed to configure dev");
+
+ iavf_dev_xstats_reset(dev);
+
+ /* start the device */
+ ret = iavf_dev_start(dev);
+ if (ret) {
+ PMD_DRV_LOG(ERR, "Failed to start dev");
+ return ret;
+ }
+
+ dev->data->dev_started = 1;
+ vf->vf_reset = false;
+
+ return 0;
+}
+
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 f7df4665d1..a1f556d1ce 100644
--- a/drivers/net/iavf/iavf_rxtx.c
+++ b/drivers/net/iavf/iavf_rxtx.c
@@ -1094,6 +1094,31 @@ iavf_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
rte_free(q);
}
+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)
{
diff --git a/drivers/net/iavf/iavf_rxtx.h b/drivers/net/iavf/iavf_rxtx.h
index 605ea3f824..237022338e 100644
--- a/drivers/net/iavf/iavf_rxtx.h
+++ b/drivers/net/iavf/iavf_rxtx.h
@@ -650,6 +650,7 @@ int iavf_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id);
int iavf_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id);
int iavf_dev_tx_done_cleanup(void *txq, uint32_t free_cnt);
void iavf_dev_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid);
+void iavf_reset_queues(struct rte_eth_dev *dev);
void iavf_stop_queues(struct rte_eth_dev *dev);
uint16_t iavf_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
uint16_t nb_pkts);
diff --git a/drivers/net/iavf/iavf_vchnl.c b/drivers/net/iavf/iavf_vchnl.c
index 524732f67d..19e22ae283 100644
--- a/drivers/net/iavf/iavf_vchnl.c
+++ b/drivers/net/iavf/iavf_vchnl.c
@@ -80,6 +80,14 @@ iavf_dev_event_handle(void *param __rte_unused)
TAILQ_FOREACH_SAFE(pos, &pending, next, save_next) {
TAILQ_REMOVE(&pending, pos, next);
rte_eth_dev_callback_process(pos->dev, pos->event, pos->param);
+
+ switch (pos->event) {
+ case RTE_ETH_EVENT_INTR_RESET:
+ iavf_handle_hw_reset(pos->dev);
+ break;
+ default:
+ break;
+ }
rte_free(pos);
}
}
--
2.37.2
next reply other threads:[~2023-08-01 2:21 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-01 9:48 Shiyang He [this message]
2023-08-11 9:40 ` [PATCH v2] " Shiyang He
2023-09-15 13:02 ` [PATCH v3] " Shiyang He
2023-09-26 7:48 ` Bruce Richardson
2023-09-26 12:15 ` Zhang, Qi Z
2023-09-26 14:05 ` Bruce Richardson
2023-09-26 23:41 ` Zhang, Qi Z
2023-09-27 6:39 ` David Marchand
2023-09-26 11:31 ` [PATCH v4] " Shiyang He
2023-09-26 4:51 ` Zhang, Qi Z
2023-09-26 12:29 ` [PATCH v5] " Shiyang He
2023-09-26 12:31 ` Shiyang He
2023-09-26 12:38 ` Shiyang He
2023-09-26 5:33 ` Zhang, Qi Z
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230801094815.4028257-1-shiyangx.he@intel.com \
--to=shiyangx.he@intel.com \
--cc=Yuying.Zhang@intel.com \
--cc=beilei.xing@intel.com \
--cc=dev@dpdk.org \
--cc=jingjing.wu@intel.com \
--cc=qiming.yang@intel.com \
--cc=simei.su@intel.com \
--cc=wenjun1.wu@intel.com \
--cc=yidingx.zhou@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).