All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wei Zhao <wei.zhao1@intel.com>
To: dev@dpdk.org
Cc: Wei Zhao <wei.zhao1@intel.com>, Wenzhuo Lu <wenzhuo.lu@intel.com>
Subject: [PATCH v6 2/3] net/i40e: implement device reset on port
Date: Thu,  6 Apr 2017 14:51:22 +0800	[thread overview]
Message-ID: <1491461483-39861-3-git-send-email-wei.zhao1@intel.com> (raw)
In-Reply-To: <1491461483-39861-1-git-send-email-wei.zhao1@intel.com>

This patch implement the device reset function on vf port.
This restart function will detach device then
attach device, reconfigure dev, re-setup
the Rx/Tx queues.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c    |   2 +-
 drivers/net/i40e/i40e_ethdev.h    |  16 ++++
 drivers/net/i40e/i40e_ethdev_vf.c | 185 ++++++++++++++++++++++++++++++++++++++
 drivers/net/i40e/i40e_rxtx.c      |  10 +++
 drivers/net/i40e/i40e_rxtx.h      |   4 +
 5 files changed, 216 insertions(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 3702214..f2fdb2f 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -6020,7 +6020,7 @@ i40e_find_vlan_filter(struct i40e_vsi *vsi,
 		return 0;
 }
 
-static void
+void
 i40e_store_vlan_filter(struct i40e_vsi *vsi,
 		       uint16_t vlan_id, bool on)
 {
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index aebb097..515a288 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -652,6 +652,16 @@ struct i40e_vf_tx_queues {
 	uint32_t tx_ring_len;
 };
 
+struct i40e_vf_reset_store {
+	struct ether_addr *mac_addrs;  /* Device Ethernet Link address. */
+	bool promisc_unicast_enabled;
+	bool promisc_multicast_enabled;
+	uint16_t vlan_num;    /* Total VLAN number */
+	uint32_t vfta[I40E_VFTA_SIZE];        /* VLAN bitmap */
+	uint16_t mac_num;        /* Total mac number */
+};
+
+
 /*
  * Structure to store private data specific for VF instance.
  */
@@ -709,6 +719,10 @@ struct i40e_adapter {
 	struct rte_timecounter systime_tc;
 	struct rte_timecounter rx_tstamp_tc;
 	struct rte_timecounter tx_tstamp_tc;
+
+	/* For port reset */
+	volatile uint8_t reset_flag;
+	void *reset_store_data;
 };
 
 extern const struct rte_flow_ops i40e_flow_ops;
@@ -749,6 +763,8 @@ int i40e_dev_link_update(struct rte_eth_dev *dev,
 			 __rte_unused int wait_to_complete);
 void i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi);
 void i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi);
+void i40e_store_vlan_filter(struct i40e_vsi *vsi,
+		       uint16_t vlan_id, bool on);
 int i40e_vsi_vlan_pvid_set(struct i40e_vsi *vsi,
 			   struct i40e_vsi_vlan_pvid_info *info);
 int i40e_vsi_config_vlan_stripping(struct i40e_vsi *vsi, bool on);
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 55fd344..9ab035c 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -161,6 +161,9 @@ i40evf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id);
 static void i40evf_handle_pf_event(__rte_unused struct rte_eth_dev *dev,
 				   uint8_t *msg,
 				   uint16_t msglen);
+static int i40evf_dev_uninit(struct rte_eth_dev *eth_dev);
+static int i40evf_dev_init(struct rte_eth_dev *eth_dev);
+static int i40evf_reset_dev(struct rte_eth_dev *dev);
 
 /* Default hash key buffer for RSS */
 static uint32_t rss_key_default[I40E_VFQF_HKEY_MAX_INDEX + 1];
@@ -230,6 +233,7 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = {
 	.rss_hash_conf_get    = i40evf_dev_rss_hash_conf_get,
 	.mtu_set              = i40evf_dev_mtu_set,
 	.mac_addr_set         = i40evf_set_default_mac_addr,
+	.dev_reset            = i40evf_reset_dev,
 };
 
 /*
@@ -889,6 +893,7 @@ i40evf_add_mac_addr(struct rte_eth_dev *dev,
 		PMD_DRV_LOG(ERR, "fail to execute command "
 			    "OP_ADD_ETHER_ADDRESS");
 
+	vf->vsi.mac_num++;
 	return;
 }
 
@@ -926,6 +931,7 @@ i40evf_del_mac_addr_by_addr(struct rte_eth_dev *dev,
 	if (err)
 		PMD_DRV_LOG(ERR, "fail to execute command "
 			    "OP_DEL_ETHER_ADDRESS");
+	vf->vsi.mac_num--;
 	return;
 }
 
@@ -1047,6 +1053,7 @@ static int
 i40evf_add_vlan(struct rte_eth_dev *dev, uint16_t vlanid)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+	struct i40e_vsi *vsi = &vf->vsi;
 	struct i40e_virtchnl_vlan_filter_list *vlan_list;
 	uint8_t cmd_buffer[sizeof(struct i40e_virtchnl_vlan_filter_list) +
 							sizeof(uint16_t)];
@@ -1066,6 +1073,8 @@ i40evf_add_vlan(struct rte_eth_dev *dev, uint16_t vlanid)
 	err = i40evf_execute_vf_cmd(dev, &args);
 	if (err)
 		PMD_DRV_LOG(ERR, "fail to execute command OP_ADD_VLAN");
+	i40e_store_vlan_filter(vsi, vlanid, 1);
+	vsi->vlan_num++;
 
 	return err;
 }
@@ -1074,6 +1083,7 @@ static int
 i40evf_del_vlan(struct rte_eth_dev *dev, uint16_t vlanid)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+	struct i40e_vsi *vsi = &vf->vsi;
 	struct i40e_virtchnl_vlan_filter_list *vlan_list;
 	uint8_t cmd_buffer[sizeof(struct i40e_virtchnl_vlan_filter_list) +
 							sizeof(uint16_t)];
@@ -1093,6 +1103,8 @@ i40evf_del_vlan(struct rte_eth_dev *dev, uint16_t vlanid)
 	err = i40evf_execute_vf_cmd(dev, &args);
 	if (err)
 		PMD_DRV_LOG(ERR, "fail to execute command OP_DEL_VLAN");
+	i40e_store_vlan_filter(vsi, vlanid, 0);
+	vsi->vlan_num--;
 
 	return err;
 }
@@ -2716,3 +2728,176 @@ i40evf_set_default_mac_addr(struct rte_eth_dev *dev,
 
 	i40evf_add_mac_addr(dev, mac_addr, 0, 0);
 }
+
+static void
+i40evf_restore_vlan_filter(struct rte_eth_dev *dev,
+			uint32_t *vfta)
+{
+	uint32_t vid_idx, vid_bit;
+	uint16_t vlan_id;
+
+	for  (vid_idx = 0; vid_idx < I40E_VFTA_SIZE; vid_idx++) {
+		for  (vid_bit = 0; vid_bit < I40E_UINT32_BIT_SIZE; vid_bit++) {
+			if (vfta[vid_idx] & (1 << vid_bit)) {
+				vlan_id = (vid_idx << 5) + vid_bit;
+				i40evf_add_vlan(dev, vlan_id);
+			}
+		}
+	}
+}
+
+static void
+i40evf_restore_macaddr(struct rte_eth_dev *dev,
+		struct ether_addr *mac_addrs)
+{
+	struct ether_addr *addr;
+	uint16_t i;
+
+	/* replay MAC address configuration including default MAC */
+	addr = &mac_addrs[0];
+
+	i40evf_set_default_mac_addr(dev, addr);
+	memcpy(dev->data->mac_addrs, mac_addrs,
+			ETHER_ADDR_LEN * I40E_NUM_MACADDR_MAX);
+
+	for (i = 1; i < I40E_NUM_MACADDR_MAX; i++) {
+		addr = &mac_addrs[i];
+
+		/* skip zero address */
+		if (is_zero_ether_addr(addr))
+			continue;
+
+		i40evf_add_mac_addr(dev, addr, 0, 0);
+	}
+}
+
+
+static void
+i40e_vf_queue_reset(struct rte_eth_dev *dev)
+{
+	uint16_t i;
+
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		struct i40e_rx_queue *rxq = dev->data->rx_queues[i];
+
+		if (rxq->q_set) {
+			i40e_dev_rx_queue_setup(dev,
+						rxq->queue_id,
+						rxq->nb_rx_desc,
+						rxq->socket_id,
+						&rxq->rxconf,
+						rxq->mp);
+		}
+	}
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		struct i40e_tx_queue *txq = dev->data->tx_queues[i];
+
+		if (txq->q_set) {
+			i40e_dev_tx_queue_setup(dev,
+						txq->queue_id,
+						txq->nb_tx_desc,
+						txq->socket_id,
+						&txq->txconf);
+		}
+	}
+}
+
+static int
+i40evf_store_before_reset(struct rte_eth_dev *dev)
+{
+	struct i40e_adapter *adapter =
+		I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct i40e_vf_reset_store *store_data;
+	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+
+	adapter->reset_store_data = rte_zmalloc("i40evf_store_reset",
+					sizeof(struct i40e_vf_reset_store), 0);
+	if (adapter->reset_store_data == NULL) {
+		PMD_INIT_LOG(ERR, "Failed to allocate %ld bytes needed to"
+				" to store data when reset vf",
+				sizeof(struct i40e_vf_reset_store));
+		return -ENOMEM;
+	}
+	store_data =
+		(struct i40e_vf_reset_store *)adapter->reset_store_data;
+	store_data->mac_addrs = rte_zmalloc("i40evf_mac_store_reset",
+			ETHER_ADDR_LEN * I40E_NUM_MACADDR_MAX, 0);
+	if (store_data->mac_addrs == NULL) {
+		PMD_INIT_LOG(ERR, "Failed to allocate %d bytes needed to"
+				" to store MAC addresses when reset vf",
+				ETHER_ADDR_LEN * I40E_NUM_MACADDR_MAX);
+	}
+
+	memcpy(store_data->mac_addrs, dev->data->mac_addrs,
+			ETHER_ADDR_LEN * I40E_NUM_MACADDR_MAX);
+
+	store_data->promisc_unicast_enabled = vf->promisc_unicast_enabled;
+	store_data->promisc_multicast_enabled = vf->promisc_multicast_enabled;
+
+	store_data->vlan_num = vf->vsi.vlan_num;
+	memcpy(store_data->vfta, vf->vsi.vfta,
+			sizeof(uint32_t) * I40E_VFTA_SIZE);
+
+	store_data->mac_num = vf->vsi.mac_num;
+
+	return 0;
+}
+
+static void
+i40evf_restore_after_reset(struct rte_eth_dev *dev)
+{
+	struct i40e_adapter *adapter =
+		I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct i40e_vf_reset_store *store_data =
+		(struct i40e_vf_reset_store *)adapter->reset_store_data;
+
+	if (store_data->promisc_unicast_enabled)
+		i40evf_dev_promiscuous_enable(dev);
+	if (store_data->promisc_multicast_enabled)
+		i40evf_dev_allmulticast_enable(dev);
+
+	if (store_data->vlan_num)
+		i40evf_restore_vlan_filter(dev, store_data->vfta);
+
+	if (store_data->mac_num)
+		i40evf_restore_macaddr(dev, store_data->mac_addrs);
+
+	rte_free(store_data->mac_addrs);
+	rte_free(adapter->reset_store_data);
+}
+
+static int
+i40evf_reset_dev(struct rte_eth_dev *dev)
+{
+	struct i40e_adapter *adapter =
+		I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+
+	adapter->reset_flag = 1;
+	i40evf_store_before_reset(dev);
+
+	i40evf_dev_close(dev);
+	PMD_DRV_LOG(DEBUG, "i40evf dev close complete");
+
+	i40evf_dev_uninit(dev);
+	PMD_DRV_LOG(DEBUG, "i40evf dev detached");
+
+	memset(dev->data->dev_private, 0,
+	       (uint64_t)&adapter->reset_flag - (uint64_t)adapter);
+
+	i40evf_dev_init(dev);
+	PMD_DRV_LOG(DEBUG, "i40evf dev attached");
+
+	i40evf_dev_configure(dev);
+
+	i40e_vf_queue_reset(dev);
+	PMD_DRV_LOG(DEBUG, "i40evf queue reset");
+
+	i40evf_restore_after_reset(dev);
+
+	i40evf_dev_start(dev);
+	PMD_DRV_LOG(DEBUG, "i40evf dev restart");
+
+	adapter->reset_flag = 0;
+
+	return 0;
+}
diff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c
index 02367b7..d891a54 100644
--- a/drivers/net/i40e/i40e_rxtx.c
+++ b/drivers/net/i40e/i40e_rxtx.c
@@ -1709,6 +1709,7 @@ i40e_dev_rx_queue_setup(struct rte_eth_dev *dev,
 	uint16_t len, i;
 	uint16_t base, bsf, tc_mapping;
 	int use_def_burst_func = 1;
+	struct rte_eth_rxconf conf = *rx_conf;
 
 	if (hw->mac.type == I40E_MAC_VF || hw->mac.type == I40E_MAC_X722_VF) {
 		struct i40e_vf *vf =
@@ -1748,6 +1749,8 @@ i40e_dev_rx_queue_setup(struct rte_eth_dev *dev,
 	}
 	rxq->mp = mp;
 	rxq->nb_rx_desc = nb_desc;
+	rxq->socket_id = socket_id;
+	rxq->rxconf = conf;
 	rxq->rx_free_thresh = rx_conf->rx_free_thresh;
 	rxq->queue_id = queue_idx;
 	if (hw->mac.type == I40E_MAC_VF || hw->mac.type == I40E_MAC_X722_VF)
@@ -1932,6 +1935,7 @@ i40e_dev_tx_queue_setup(struct rte_eth_dev *dev,
 	uint32_t ring_size;
 	uint16_t tx_rs_thresh, tx_free_thresh;
 	uint16_t i, base, bsf, tc_mapping;
+	struct rte_eth_txconf conf = *tx_conf;
 
 	if (hw->mac.type == I40E_MAC_VF || hw->mac.type == I40E_MAC_X722_VF) {
 		struct i40e_vf *vf =
@@ -2054,6 +2058,8 @@ i40e_dev_tx_queue_setup(struct rte_eth_dev *dev,
 	}
 
 	txq->nb_tx_desc = nb_desc;
+	txq->socket_id = socket_id;
+	txq->txconf = conf;
 	txq->tx_rs_thresh = tx_rs_thresh;
 	txq->tx_free_thresh = tx_free_thresh;
 	txq->pthresh = tx_conf->tx_thresh.pthresh;
@@ -2520,8 +2526,12 @@ void
 i40e_dev_free_queues(struct rte_eth_dev *dev)
 {
 	uint16_t i;
+	struct i40e_adapter *adapter =
+		I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
 
 	PMD_INIT_FUNC_TRACE();
+	if (adapter->reset_flag)
+		return;
 
 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
 		if (!dev->data->rx_queues[i])
diff --git a/drivers/net/i40e/i40e_rxtx.h b/drivers/net/i40e/i40e_rxtx.h
index a87bdb0..0e3cc19 100644
--- a/drivers/net/i40e/i40e_rxtx.h
+++ b/drivers/net/i40e/i40e_rxtx.h
@@ -136,6 +136,8 @@ struct i40e_rx_queue {
 	bool rx_deferred_start; /**< don't start this queue in dev start */
 	uint16_t rx_using_sse; /**<flag indicate the usage of vPMD for rx */
 	uint8_t dcb_tc;         /**< Traffic class of rx queue */
+	uint8_t socket_id;
+	struct rte_eth_rxconf rxconf;
 };
 
 struct i40e_tx_entry {
@@ -177,6 +179,8 @@ struct i40e_tx_queue {
 	bool q_set; /**< indicate if tx queue has been configured */
 	bool tx_deferred_start; /**< don't start this queue in dev start */
 	uint8_t dcb_tc;         /**< Traffic class of tx queue */
+	uint8_t socket_id;
+	struct rte_eth_txconf txconf;
 };
 
 /** Offload features */
-- 
2.9.3

  parent reply	other threads:[~2017-04-06  6:57 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-30  9:34 [PATCH v4 0/3] net/i40e: vf port reset Wei Zhao
2017-03-30  9:34 ` [PATCH v4 1/3] lib/librte_ether: add support for " Wei Zhao
2017-03-30 19:55   ` Thomas Monjalon
2017-04-06  2:57     ` Zhao1, Wei
2017-04-06  7:11       ` Thomas Monjalon
2017-04-06  8:53         ` Zhao1, Wei
2017-04-06  9:02           ` Ananyev, Konstantin
2017-04-10 20:58             ` Thomas Monjalon
2017-04-13  8:55             ` Zhao1, Wei
2017-04-13 10:06               ` Thomas Monjalon
2017-04-14  1:29                 ` Zhao1, Wei
2017-04-14  6:31                   ` Thomas Monjalon
2017-04-14  8:03                     ` Zhao1, Wei
2017-04-17  2:08                       ` Zhao1, Wei
2017-04-17  5:02                         ` Zhao1, Wei
2017-04-20  6:07       ` Yuanhan Liu
2017-04-20  9:17         ` Zhao1, Wei
2017-04-21  2:27           ` Yuanhan Liu
2017-04-21  8:27             ` Thomas Monjalon
2017-04-21  8:59               ` Zhao1, Wei
2017-04-21  9:28                 ` Thomas Monjalon
2017-04-24  2:01                   ` Yuanhan Liu
2017-04-24  3:15                     ` Zhao1, Wei
2017-04-24  3:39                     ` Zhao1, Wei
2017-04-24  8:04                       ` Thomas Monjalon
2017-04-25  3:14                         ` Zhao1, Wei
2017-04-21  8:55             ` Zhao1, Wei
2017-03-30  9:34 ` [PATCH v4 2/3] net/i40e: implement device reset on port Wei Zhao
2017-03-30  9:34 ` [PATCH v4 3/3] app/testpmd: add port reset command into testpmd Wei Zhao
2017-03-30 12:32 ` [PATCH v4 0/3] net/i40e: vf port reset Wu, Jingjing
2017-04-05  5:42   ` Zhao1, Wei
2017-04-06  6:33 ` [PATCH v5 " Wei Zhao
2017-04-06  6:33   ` [PATCH v5 1/3] lib/librte_ether: add support for " Wei Zhao
2017-04-06  6:33   ` [PATCH v5 2/3] net/i40e: implement device reset on port Wei Zhao
2017-04-06  6:33   ` [PATCH v5 3/3] app/testpmd: add port reset command into testpmd Wei Zhao
2017-04-06  6:51   ` [PATCH v6 0/3] net/i40e: vf port reset Wei Zhao
2017-04-06  6:51     ` [PATCH v6 1/3] lib/librte_ether: add support for " Wei Zhao
2017-04-07  6:58       ` Yang, Qiming
2017-04-10  2:21         ` Zhao1, Wei
2017-04-06  6:51     ` Wei Zhao [this message]
2017-04-06  6:51     ` [PATCH v6 3/3] app/testpmd: add port reset command into testpmd Wei Zhao
2017-04-10  3:02     ` [PATCH v7 0/3] net/i40e: vf port reset Wei Zhao
2017-04-10  3:02       ` [PATCH v7 1/3] lib/librte_ether: add support for " Wei Zhao
2017-04-20 20:49         ` Thomas Monjalon
2017-04-21  3:20           ` Zhao1, Wei
2017-04-20 20:52         ` Thomas Monjalon
2017-04-10  3:02       ` [PATCH v7 2/3] net/i40e: implement device reset on port Wei Zhao
2017-04-20 21:12         ` Thomas Monjalon
2017-04-21  3:39           ` Zhao1, Wei
2017-04-20 21:20         ` Thomas Monjalon
2017-04-10  3:02       ` [PATCH v7 3/3] app/testpmd: add port reset command into testpmd Wei Zhao
2017-04-20 21:37       ` [PATCH v7 0/3] net/i40e: vf port reset Thomas Monjalon

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=1491461483-39861-3-git-send-email-wei.zhao1@intel.com \
    --to=wei.zhao1@intel.com \
    --cc=dev@dpdk.org \
    --cc=wenzhuo.lu@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.