All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jiawen Wu <jiawenwu@trustnetic.com>
To: dev@dpdk.org
Cc: Jiawen Wu <jiawenwu@trustnetic.com>
Subject: [dpdk-dev] [PATCH v1 02/20] net/txgbe: add base code for VF driver
Date: Fri, 22 Jan 2021 17:47:42 +0800	[thread overview]
Message-ID: <20210122094800.197748-3-jiawenwu@trustnetic.com> (raw)
In-Reply-To: <20210122094800.197748-1-jiawenwu@trustnetic.com>

Implement VF device init and uninit function with hardware operations,
and negotiate with PF in mailbox.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 drivers/net/txgbe/base/meson.build  |   1 +
 drivers/net/txgbe/base/txgbe.h      |   1 +
 drivers/net/txgbe/base/txgbe_hw.c   |   4 +
 drivers/net/txgbe/base/txgbe_mbx.c  | 354 ++++++++++++++++++++++++++++
 drivers/net/txgbe/base/txgbe_mbx.h  |  16 ++
 drivers/net/txgbe/base/txgbe_type.h |   7 +
 drivers/net/txgbe/base/txgbe_vf.c   | 285 ++++++++++++++++++++++
 drivers/net/txgbe/base/txgbe_vf.h   |  20 ++
 drivers/net/txgbe/txgbe_ethdev_vf.c | 115 +++++++++
 9 files changed, 803 insertions(+)
 create mode 100644 drivers/net/txgbe/base/txgbe_vf.c
 create mode 100644 drivers/net/txgbe/base/txgbe_vf.h

diff --git a/drivers/net/txgbe/base/meson.build b/drivers/net/txgbe/base/meson.build
index 3c63bf5f4..33d0adf0d 100644
--- a/drivers/net/txgbe/base/meson.build
+++ b/drivers/net/txgbe/base/meson.build
@@ -9,6 +9,7 @@ sources = [
 	'txgbe_mbx.c',
 	'txgbe_mng.c',
 	'txgbe_phy.c',
+	'txgbe_vf.c',
 ]
 
 error_cflags = []
diff --git a/drivers/net/txgbe/base/txgbe.h b/drivers/net/txgbe/base/txgbe.h
index b054bb8d0..d7199512b 100644
--- a/drivers/net/txgbe/base/txgbe.h
+++ b/drivers/net/txgbe/base/txgbe.h
@@ -11,6 +11,7 @@
 #include "txgbe_eeprom.h"
 #include "txgbe_phy.h"
 #include "txgbe_hw.h"
+#include "txgbe_vf.h"
 #include "txgbe_dcb.h"
 
 #endif /* _TXGBE_H_ */
diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c
index dc419d7d4..c357c8658 100644
--- a/drivers/net/txgbe/base/txgbe_hw.c
+++ b/drivers/net/txgbe/base/txgbe_hw.c
@@ -6,6 +6,7 @@
 #include "txgbe_mbx.h"
 #include "txgbe_phy.h"
 #include "txgbe_dcb.h"
+#include "txgbe_vf.h"
 #include "txgbe_eeprom.h"
 #include "txgbe_mng.h"
 #include "txgbe_hw.h"
@@ -2491,6 +2492,9 @@ s32 txgbe_init_shared_code(struct txgbe_hw *hw)
 	case txgbe_mac_raptor:
 		status = txgbe_init_ops_pf(hw);
 		break;
+	case txgbe_mac_raptor_vf:
+		status = txgbe_init_ops_vf(hw);
+		break;
 	default:
 		status = TXGBE_ERR_DEVICE_NOT_SUPPORTED;
 		break;
diff --git a/drivers/net/txgbe/base/txgbe_mbx.c b/drivers/net/txgbe/base/txgbe_mbx.c
index bfe53478e..b308839e7 100644
--- a/drivers/net/txgbe/base/txgbe_mbx.c
+++ b/drivers/net/txgbe/base/txgbe_mbx.c
@@ -118,6 +118,360 @@ s32 txgbe_check_for_rst(struct txgbe_hw *hw, u16 mbx_id)
 	return ret_val;
 }
 
+/**
+ *  txgbe_poll_for_msg - Wait for message notification
+ *  @hw: pointer to the HW structure
+ *  @mbx_id: id of mailbox to write
+ *
+ *  returns SUCCESS if it successfully received a message notification
+ **/
+STATIC s32 txgbe_poll_for_msg(struct txgbe_hw *hw, u16 mbx_id)
+{
+	struct txgbe_mbx_info *mbx = &hw->mbx;
+	int countdown = mbx->timeout;
+
+	DEBUGFUNC("txgbe_poll_for_msg");
+
+	if (!countdown || !mbx->check_for_msg)
+		goto out;
+
+	while (countdown && mbx->check_for_msg(hw, mbx_id)) {
+		countdown--;
+		if (!countdown)
+			break;
+		usec_delay(mbx->usec_delay);
+	}
+
+	if (countdown == 0)
+		DEBUGOUT("Polling for VF%d mailbox message timedout", mbx_id);
+
+out:
+	return countdown ? 0 : TXGBE_ERR_MBX;
+}
+
+/**
+ *  txgbe_poll_for_ack - Wait for message acknowledgment
+ *  @hw: pointer to the HW structure
+ *  @mbx_id: id of mailbox to write
+ *
+ *  returns SUCCESS if it successfully received a message acknowledgment
+ **/
+STATIC s32 txgbe_poll_for_ack(struct txgbe_hw *hw, u16 mbx_id)
+{
+	struct txgbe_mbx_info *mbx = &hw->mbx;
+	int countdown = mbx->timeout;
+
+	DEBUGFUNC("txgbe_poll_for_ack");
+
+	if (!countdown || !mbx->check_for_ack)
+		goto out;
+
+	while (countdown && mbx->check_for_ack(hw, mbx_id)) {
+		countdown--;
+		if (!countdown)
+			break;
+		usec_delay(mbx->usec_delay);
+	}
+
+	if (countdown == 0)
+		DEBUGOUT("Polling for VF%d mailbox ack timedout", mbx_id);
+
+out:
+	return countdown ? 0 : TXGBE_ERR_MBX;
+}
+
+/**
+ *  txgbe_read_posted_mbx - Wait for message notification and receive message
+ *  @hw: pointer to the HW structure
+ *  @msg: The message buffer
+ *  @size: Length of buffer
+ *  @mbx_id: id of mailbox to write
+ *
+ *  returns SUCCESS if it successfully received a message notification and
+ *  copied it into the receive buffer.
+ **/
+s32 txgbe_read_posted_mbx(struct txgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id)
+{
+	struct txgbe_mbx_info *mbx = &hw->mbx;
+	s32 ret_val = TXGBE_ERR_MBX;
+
+	DEBUGFUNC("txgbe_read_posted_mbx");
+
+	if (!mbx->read)
+		goto out;
+
+	ret_val = txgbe_poll_for_msg(hw, mbx_id);
+
+	/* if ack received read message, otherwise we timed out */
+	if (!ret_val)
+		ret_val = mbx->read(hw, msg, size, mbx_id);
+out:
+	return ret_val;
+}
+
+/**
+ *  txgbe_write_posted_mbx - Write a message to the mailbox, wait for ack
+ *  @hw: pointer to the HW structure
+ *  @msg: The message buffer
+ *  @size: Length of buffer
+ *  @mbx_id: id of mailbox to write
+ *
+ *  returns SUCCESS if it successfully copied message into the buffer and
+ *  received an ack to that message within delay * timeout period
+ **/
+s32 txgbe_write_posted_mbx(struct txgbe_hw *hw, u32 *msg, u16 size,
+			   u16 mbx_id)
+{
+	struct txgbe_mbx_info *mbx = &hw->mbx;
+	s32 ret_val = TXGBE_ERR_MBX;
+
+	DEBUGFUNC("txgbe_write_posted_mbx");
+
+	/* exit if either we can't write or there isn't a defined timeout */
+	if (!mbx->write || !mbx->timeout)
+		goto out;
+
+	/* send msg */
+	ret_val = mbx->write(hw, msg, size, mbx_id);
+
+	/* if msg sent wait until we receive an ack */
+	if (!ret_val)
+		ret_val = txgbe_poll_for_ack(hw, mbx_id);
+out:
+	return ret_val;
+}
+
+/**
+ *  txgbe_read_v2p_mailbox - read v2p mailbox
+ *  @hw: pointer to the HW structure
+ *
+ *  This function is used to read the v2p mailbox without losing the read to
+ *  clear status bits.
+ **/
+STATIC u32 txgbe_read_v2p_mailbox(struct txgbe_hw *hw)
+{
+	u32 v2p_mailbox = rd32(hw, TXGBE_VFMBCTL);
+
+	v2p_mailbox |= hw->mbx.v2p_mailbox;
+	hw->mbx.v2p_mailbox |= v2p_mailbox & TXGBE_VFMBCTL_R2C_BITS;
+
+	return v2p_mailbox;
+}
+
+/**
+ *  txgbe_check_for_bit_vf - Determine if a status bit was set
+ *  @hw: pointer to the HW structure
+ *  @mask: bitmask for bits to be tested and cleared
+ *
+ *  This function is used to check for the read to clear bits within
+ *  the V2P mailbox.
+ **/
+STATIC s32 txgbe_check_for_bit_vf(struct txgbe_hw *hw, u32 mask)
+{
+	u32 v2p_mailbox = txgbe_read_v2p_mailbox(hw);
+	s32 ret_val = TXGBE_ERR_MBX;
+
+	if (v2p_mailbox & mask)
+		ret_val = 0;
+
+	hw->mbx.v2p_mailbox &= ~mask;
+
+	return ret_val;
+}
+
+/**
+ *  txgbe_check_for_msg_vf - checks to see if the PF has sent mail
+ *  @hw: pointer to the HW structure
+ *  @mbx_id: id of mailbox to check
+ *
+ *  returns SUCCESS if the PF has set the Status bit or else ERR_MBX
+ **/
+s32 txgbe_check_for_msg_vf(struct txgbe_hw *hw, u16 mbx_id)
+{
+	s32 ret_val = TXGBE_ERR_MBX;
+
+	UNREFERENCED_PARAMETER(mbx_id);
+	DEBUGFUNC("txgbe_check_for_msg_vf");
+
+	if (!txgbe_check_for_bit_vf(hw, TXGBE_VFMBCTL_PFSTS)) {
+		ret_val = 0;
+		hw->mbx.stats.reqs++;
+	}
+
+	return ret_val;
+}
+
+/**
+ *  txgbe_check_for_ack_vf - checks to see if the PF has ACK'd
+ *  @hw: pointer to the HW structure
+ *  @mbx_id: id of mailbox to check
+ *
+ *  returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
+ **/
+s32 txgbe_check_for_ack_vf(struct txgbe_hw *hw, u16 mbx_id)
+{
+	s32 ret_val = TXGBE_ERR_MBX;
+
+	UNREFERENCED_PARAMETER(mbx_id);
+	DEBUGFUNC("txgbe_check_for_ack_vf");
+
+	if (!txgbe_check_for_bit_vf(hw, TXGBE_VFMBCTL_PFACK)) {
+		ret_val = 0;
+		hw->mbx.stats.acks++;
+	}
+
+	return ret_val;
+}
+
+/**
+ *  txgbe_check_for_rst_vf - checks to see if the PF has reset
+ *  @hw: pointer to the HW structure
+ *  @mbx_id: id of mailbox to check
+ *
+ *  returns true if the PF has set the reset done bit or else false
+ **/
+s32 txgbe_check_for_rst_vf(struct txgbe_hw *hw, u16 mbx_id)
+{
+	s32 ret_val = TXGBE_ERR_MBX;
+
+	UNREFERENCED_PARAMETER(mbx_id);
+	DEBUGFUNC("txgbe_check_for_rst_vf");
+
+	if (!txgbe_check_for_bit_vf(hw, (TXGBE_VFMBCTL_RSTD |
+	    TXGBE_VFMBCTL_RSTI))) {
+		ret_val = 0;
+		hw->mbx.stats.rsts++;
+	}
+
+	return ret_val;
+}
+
+/**
+ *  txgbe_obtain_mbx_lock_vf - obtain mailbox lock
+ *  @hw: pointer to the HW structure
+ *
+ *  return SUCCESS if we obtained the mailbox lock
+ **/
+STATIC s32 txgbe_obtain_mbx_lock_vf(struct txgbe_hw *hw)
+{
+	s32 ret_val = TXGBE_ERR_MBX;
+
+	DEBUGFUNC("txgbe_obtain_mbx_lock_vf");
+
+	/* Take ownership of the buffer */
+	wr32(hw, TXGBE_VFMBCTL, TXGBE_VFMBCTL_VFU);
+
+	/* reserve mailbox for vf use */
+	if (txgbe_read_v2p_mailbox(hw) & TXGBE_VFMBCTL_VFU)
+		ret_val = 0;
+
+	return ret_val;
+}
+
+/**
+ *  txgbe_write_mbx_vf - Write a message to the mailbox
+ *  @hw: pointer to the HW structure
+ *  @msg: The message buffer
+ *  @size: Length of buffer
+ *  @mbx_id: id of mailbox to write
+ *
+ *  returns SUCCESS if it successfully copied message into the buffer
+ **/
+s32 txgbe_write_mbx_vf(struct txgbe_hw *hw, u32 *msg, u16 size,
+			      u16 mbx_id)
+{
+	s32 ret_val;
+	u16 i;
+
+	UNREFERENCED_PARAMETER(mbx_id);
+
+	DEBUGFUNC("txgbe_write_mbx_vf");
+
+	/* lock the mailbox to prevent pf/vf race condition */
+	ret_val = txgbe_obtain_mbx_lock_vf(hw);
+	if (ret_val)
+		goto out_no_write;
+
+	/* flush msg and acks as we are overwriting the message buffer */
+	txgbe_check_for_msg_vf(hw, 0);
+	txgbe_check_for_ack_vf(hw, 0);
+
+	/* copy the caller specified message to the mailbox memory buffer */
+	for (i = 0; i < size; i++)
+		wr32a(hw, TXGBE_VFMBX, i, msg[i]);
+
+	/* update stats */
+	hw->mbx.stats.msgs_tx++;
+
+	/* Drop VFU and interrupt the PF to tell it a message has been sent */
+	wr32(hw, TXGBE_VFMBCTL, TXGBE_VFMBCTL_REQ);
+
+out_no_write:
+	return ret_val;
+}
+
+/**
+ *  txgbe_read_mbx_vf - Reads a message from the inbox intended for vf
+ *  @hw: pointer to the HW structure
+ *  @msg: The message buffer
+ *  @size: Length of buffer
+ *  @mbx_id: id of mailbox to read
+ *
+ *  returns SUCCESS if it successfully read message from buffer
+ **/
+s32 txgbe_read_mbx_vf(struct txgbe_hw *hw, u32 *msg, u16 size,
+			     u16 mbx_id)
+{
+	s32 ret_val = 0;
+	u16 i;
+
+	DEBUGFUNC("txgbe_read_mbx_vf");
+	UNREFERENCED_PARAMETER(mbx_id);
+
+	/* lock the mailbox to prevent pf/vf race condition */
+	ret_val = txgbe_obtain_mbx_lock_vf(hw);
+	if (ret_val)
+		goto out_no_read;
+
+	/* copy the message from the mailbox memory buffer */
+	for (i = 0; i < size; i++)
+		msg[i] = rd32a(hw, TXGBE_VFMBX, i);
+
+	/* Acknowledge receipt and release mailbox, then we're done */
+	wr32(hw, TXGBE_VFMBCTL, TXGBE_VFMBCTL_ACK);
+
+	/* update stats */
+	hw->mbx.stats.msgs_rx++;
+
+out_no_read:
+	return ret_val;
+}
+
+/**
+ *  txgbe_init_mbx_params_vf - set initial values for vf mailbox
+ *  @hw: pointer to the HW structure
+ *
+ *  Initializes the hw->mbx struct to correct values for vf mailbox
+ */
+void txgbe_init_mbx_params_vf(struct txgbe_hw *hw)
+{
+	struct txgbe_mbx_info *mbx = &hw->mbx;
+
+	/* start mailbox as timed out and let the reset_hw call set the timeout
+	 * value to begin communications
+	 */
+	mbx->timeout = 0;
+	mbx->usec_delay = TXGBE_VF_MBX_INIT_DELAY;
+
+	mbx->size = TXGBE_P2VMBX_SIZE;
+
+	mbx->stats.msgs_tx = 0;
+	mbx->stats.msgs_rx = 0;
+	mbx->stats.reqs = 0;
+	mbx->stats.acks = 0;
+	mbx->stats.rsts = 0;
+}
+
 STATIC s32 txgbe_check_for_bit_pf(struct txgbe_hw *hw, u32 mask, s32 index)
 {
 	u32 mbvficr = rd32(hw, TXGBE_MBVFICR(index));
diff --git a/drivers/net/txgbe/base/txgbe_mbx.h b/drivers/net/txgbe/base/txgbe_mbx.h
index 4a058b0bb..ccf5d12f2 100644
--- a/drivers/net/txgbe/base/txgbe_mbx.h
+++ b/drivers/net/txgbe/base/txgbe_mbx.h
@@ -60,6 +60,8 @@ enum txgbe_pfvf_api_rev {
 #define TXGBE_VF_GET_RSS_KEY	0x0b    /* get RSS key */
 #define TXGBE_VF_UPDATE_XCAST_MODE	0x0c
 
+#define TXGBE_VF_BACKUP		0x8001 /* VF requests backup */
+
 /* mode choices for TXGBE_VF_UPDATE_XCAST_MODE */
 enum txgbevf_xcast_modes {
 	TXGBEVF_XCAST_MODE_NONE = 0,
@@ -76,12 +78,20 @@ enum txgbevf_xcast_modes {
 
 /* length of permanent address message returned from PF */
 #define TXGBE_VF_PERMADDR_MSG_LEN	4
+/* word in permanent address message with the current multicast type */
+#define TXGBE_VF_MC_TYPE_WORD		3
+
+#define TXGBE_VF_MBX_INIT_TIMEOUT	2000 /* number of retries on mailbox */
+#define TXGBE_VF_MBX_INIT_DELAY		500  /* microseconds between retries */
 
 s32 txgbe_read_mbx(struct txgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id);
 s32 txgbe_write_mbx(struct txgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id);
+s32 txgbe_read_posted_mbx(struct txgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id);
+s32 txgbe_write_posted_mbx(struct txgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id);
 s32 txgbe_check_for_msg(struct txgbe_hw *hw, u16 mbx_id);
 s32 txgbe_check_for_ack(struct txgbe_hw *hw, u16 mbx_id);
 s32 txgbe_check_for_rst(struct txgbe_hw *hw, u16 mbx_id);
+void txgbe_init_mbx_params_vf(struct txgbe_hw *hw);
 void txgbe_init_mbx_params_pf(struct txgbe_hw *hw);
 
 s32 txgbe_read_mbx_pf(struct txgbe_hw *hw, u32 *msg, u16 size, u16 vf_number);
@@ -90,4 +100,10 @@ s32 txgbe_check_for_msg_pf(struct txgbe_hw *hw, u16 vf_number);
 s32 txgbe_check_for_ack_pf(struct txgbe_hw *hw, u16 vf_number);
 s32 txgbe_check_for_rst_pf(struct txgbe_hw *hw, u16 vf_number);
 
+s32 txgbe_read_mbx_vf(struct txgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id);
+s32 txgbe_write_mbx_vf(struct txgbe_hw *hw, u32 *msg, u16 size, u16 mbx_id);
+s32 txgbe_check_for_msg_vf(struct txgbe_hw *hw, u16 mbx_id);
+s32 txgbe_check_for_ack_vf(struct txgbe_hw *hw, u16 mbx_id);
+s32 txgbe_check_for_rst_vf(struct txgbe_hw *hw, u16 mbx_id);
+
 #endif /* _TXGBE_MBX_H_ */
diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h
index 22efcef78..ef8358ae3 100644
--- a/drivers/net/txgbe/base/txgbe_type.h
+++ b/drivers/net/txgbe/base/txgbe_type.h
@@ -11,6 +11,9 @@
 #define TXGBE_LINK_UP_TIME	90 /* 9.0 Seconds */
 #define TXGBE_AUTO_NEG_TIME	45 /* 4.5 Seconds */
 
+#define TXGBE_RX_HDR_SIZE	256
+#define TXGBE_RX_BUF_SIZE	2048
+
 #define TXGBE_FRAME_SIZE_MAX	(9728) /* Maximum frame size, +FCS */
 #define TXGBE_FRAME_SIZE_DFT	(1518) /* Default frame size, +FCS */
 #define TXGBE_NUM_POOL		(64)
@@ -23,6 +26,7 @@
 
 #define TXGBE_FDIR_INIT_DONE_POLL		10
 #define TXGBE_FDIRCMD_CMD_POLL			10
+#define TXGBE_VF_INIT_TIMEOUT	200 /* Number of retries to clear RSTI */
 
 #define TXGBE_ALIGN		128 /* as intel did */
 
@@ -703,6 +707,7 @@ struct txgbe_mbx_info {
 	struct txgbe_mbx_stats stats;
 	u32 timeout;
 	u32 usec_delay;
+	u32 v2p_mailbox;
 	u16 size;
 };
 
@@ -732,6 +737,7 @@ struct txgbe_hw {
 	u16 subsystem_vendor_id;
 	u8 revision_id;
 	bool adapter_stopped;
+	int api_version;
 	bool allow_unsupported_sfp;
 	bool need_crosstalk_fix;
 
@@ -755,6 +761,7 @@ struct txgbe_hw {
 	u32 q_rx_regs[128 * 4];
 	u32 q_tx_regs[128 * 4];
 	bool offset_loaded;
+	bool rx_loaded;
 	struct {
 		u64 rx_qp_packets;
 		u64 tx_qp_packets;
diff --git a/drivers/net/txgbe/base/txgbe_vf.c b/drivers/net/txgbe/base/txgbe_vf.c
new file mode 100644
index 000000000..30bc0e40d
--- /dev/null
+++ b/drivers/net/txgbe/base/txgbe_vf.c
@@ -0,0 +1,285 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015-2020
+ */
+
+#include "txgbe_mbx.h"
+#include "txgbe_vf.h"
+
+/**
+ *  txgbe_init_ops_vf - Initialize the pointers for vf
+ *  @hw: pointer to hardware structure
+ *
+ *  This will assign function pointers, adapter-specific functions can
+ *  override the assignment of generic function pointers by assigning
+ *  their own adapter-specific function pointers.
+ *  Does not touch the hardware.
+ **/
+s32 txgbe_init_ops_vf(struct txgbe_hw *hw)
+{
+	struct txgbe_mac_info *mac = &hw->mac;
+	struct txgbe_mbx_info *mbx = &hw->mbx;
+
+	/* MAC */
+	mac->reset_hw = txgbe_reset_hw_vf;
+	mac->stop_hw = txgbe_stop_hw_vf;
+	mac->negotiate_api_version = txgbevf_negotiate_api_version;
+
+	mac->max_tx_queues = 1;
+	mac->max_rx_queues = 1;
+
+	mbx->init_params = txgbe_init_mbx_params_vf;
+	mbx->read = txgbe_read_mbx_vf;
+	mbx->write = txgbe_write_mbx_vf;
+	mbx->read_posted = txgbe_read_posted_mbx;
+	mbx->write_posted = txgbe_write_posted_mbx;
+	mbx->check_for_msg = txgbe_check_for_msg_vf;
+	mbx->check_for_ack = txgbe_check_for_ack_vf;
+	mbx->check_for_rst = txgbe_check_for_rst_vf;
+
+	return 0;
+}
+
+/* txgbe_virt_clr_reg - Set register to default (power on) state.
+ * @hw: pointer to hardware structure
+ */
+static void txgbe_virt_clr_reg(struct txgbe_hw *hw)
+{
+	int i;
+	u32 vfsrrctl;
+
+	/* default values (BUF_SIZE = 2048, HDR_SIZE = 256) */
+	vfsrrctl = TXGBE_RXCFG_HDRLEN(TXGBE_RX_HDR_SIZE);
+	vfsrrctl |= TXGBE_RXCFG_PKTLEN(TXGBE_RX_BUF_SIZE);
+
+	for (i = 0; i < 8; i++) {
+		wr32m(hw, TXGBE_RXCFG(i),
+			(TXGBE_RXCFG_HDRLEN_MASK | TXGBE_RXCFG_PKTLEN_MASK),
+			vfsrrctl);
+	}
+
+	txgbe_flush(hw);
+}
+
+/**
+ *  txgbe_reset_hw_vf - Performs hardware reset
+ *  @hw: pointer to hardware structure
+ *
+ *  Resets the hardware by resetting the transmit and receive units, masks and
+ *  clears all interrupts.
+ **/
+s32 txgbe_reset_hw_vf(struct txgbe_hw *hw)
+{
+	struct txgbe_mbx_info *mbx = &hw->mbx;
+	u32 timeout = TXGBE_VF_INIT_TIMEOUT;
+	s32 ret_val = TXGBE_ERR_INVALID_MAC_ADDR;
+	u32 msgbuf[TXGBE_VF_PERMADDR_MSG_LEN];
+	u8 *addr = (u8 *)(&msgbuf[1]);
+
+	DEBUGFUNC("txgbevf_reset_hw_vf");
+
+	/* Call adapter stop to disable tx/rx and clear interrupts */
+	hw->mac.stop_hw(hw);
+
+	/* reset the api version */
+	hw->api_version = txgbe_mbox_api_10;
+
+	/* backup msix vectors */
+	mbx->timeout = TXGBE_VF_MBX_INIT_TIMEOUT;
+	msgbuf[0] = TXGBE_VF_BACKUP;
+	mbx->write_posted(hw, msgbuf, 1, 0);
+	msec_delay(10);
+
+	DEBUGOUT("Issuing a function level reset to MAC\n");
+	wr32(hw, TXGBE_VFRST, TXGBE_VFRST_SET);
+	txgbe_flush(hw);
+	msec_delay(50);
+
+	hw->offset_loaded = 1;
+
+	/* we cannot reset while the RSTI / RSTD bits are asserted */
+	while (!mbx->check_for_rst(hw, 0) && timeout) {
+		timeout--;
+		/* if it doesn't work, try in 1 ms */
+		usec_delay(5);
+	}
+
+	if (!timeout)
+		return TXGBE_ERR_RESET_FAILED;
+
+	/* Reset VF registers to initial values */
+	txgbe_virt_clr_reg(hw);
+
+	/* mailbox timeout can now become active */
+	mbx->timeout = TXGBE_VF_MBX_INIT_TIMEOUT;
+
+	msgbuf[0] = TXGBE_VF_RESET;
+	mbx->write_posted(hw, msgbuf, 1, 0);
+
+	msec_delay(10);
+
+	/*
+	 * set our "perm_addr" based on info provided by PF
+	 * also set up the mc_filter_type which is piggy backed
+	 * on the mac address in word 3
+	 */
+	ret_val = mbx->read_posted(hw, msgbuf,
+			TXGBE_VF_PERMADDR_MSG_LEN, 0);
+	if (ret_val)
+		return ret_val;
+
+	if (msgbuf[0] != (TXGBE_VF_RESET | TXGBE_VT_MSGTYPE_ACK) &&
+	    msgbuf[0] != (TXGBE_VF_RESET | TXGBE_VT_MSGTYPE_NACK))
+		return TXGBE_ERR_INVALID_MAC_ADDR;
+
+	if (msgbuf[0] == (TXGBE_VF_RESET | TXGBE_VT_MSGTYPE_ACK))
+		memcpy(hw->mac.perm_addr, addr, ETH_ADDR_LEN);
+
+	hw->mac.mc_filter_type = msgbuf[TXGBE_VF_MC_TYPE_WORD];
+
+	return ret_val;
+}
+
+/**
+ *  txgbe_stop_hw_vf - Generic stop Tx/Rx units
+ *  @hw: pointer to hardware structure
+ *
+ *  Sets the adapter_stopped flag within txgbe_hw struct. Clears interrupts,
+ *  disables transmit and receive units. The adapter_stopped flag is used by
+ *  the shared code and drivers to determine if the adapter is in a stopped
+ *  state and should not touch the hardware.
+ **/
+s32 txgbe_stop_hw_vf(struct txgbe_hw *hw)
+{
+	u16 i;
+
+	/*
+	 * Set the adapter_stopped flag so other driver functions stop touching
+	 * the hardware
+	 */
+	hw->adapter_stopped = true;
+
+	/* Clear interrupt mask to stop from interrupts being generated */
+	wr32(hw, TXGBE_VFIMC, TXGBE_VFIMC_MASK);
+
+	/* Clear any pending interrupts, flush previous writes */
+	wr32(hw, TXGBE_VFICR, TXGBE_VFICR_MASK);
+
+	/* Disable the transmit unit.  Each queue must be disabled. */
+	for (i = 0; i < hw->mac.max_tx_queues; i++)
+		wr32(hw, TXGBE_TXCFG(i), TXGBE_TXCFG_FLUSH);
+
+	/* Disable the receive unit by stopping each queue */
+	for (i = 0; i < hw->mac.max_rx_queues; i++)
+		wr32m(hw, TXGBE_RXCFG(i), TXGBE_RXCFG_ENA, 0);
+
+	/* Clear packet split and pool config */
+	wr32(hw, TXGBE_VFPLCFG, 0);
+	hw->rx_loaded = 1;
+
+	/* flush all queues disables */
+	txgbe_flush(hw);
+	msec_delay(2);
+
+	return 0;
+}
+
+STATIC s32 txgbevf_write_msg_read_ack(struct txgbe_hw *hw, u32 *msg,
+				      u32 *retmsg, u16 size)
+{
+	struct txgbe_mbx_info *mbx = &hw->mbx;
+	s32 retval = mbx->write_posted(hw, msg, size, 0);
+
+	if (retval)
+		return retval;
+
+	return mbx->read_posted(hw, retmsg, size, 0);
+}
+
+/**
+ *  txgbevf_negotiate_api_version - Negotiate supported API version
+ *  @hw: pointer to the HW structure
+ *  @api: integer containing requested API version
+ **/
+int txgbevf_negotiate_api_version(struct txgbe_hw *hw, int api)
+{
+	int err;
+	u32 msg[3];
+
+	/* Negotiate the mailbox API version */
+	msg[0] = TXGBE_VF_API_NEGOTIATE;
+	msg[1] = api;
+	msg[2] = 0;
+
+	err = txgbevf_write_msg_read_ack(hw, msg, msg, 3);
+	if (!err) {
+		msg[0] &= ~TXGBE_VT_MSGTYPE_CTS;
+
+		/* Store value and return 0 on success */
+		if (msg[0] == (TXGBE_VF_API_NEGOTIATE | TXGBE_VT_MSGTYPE_ACK)) {
+			hw->api_version = api;
+			return 0;
+		}
+
+		err = TXGBE_ERR_INVALID_ARGUMENT;
+	}
+
+	return err;
+}
+
+int txgbevf_get_queues(struct txgbe_hw *hw, unsigned int *num_tcs,
+		       unsigned int *default_tc)
+{
+	int err, i;
+	u32 msg[5];
+
+	/* do nothing if API doesn't support txgbevf_get_queues */
+	switch (hw->api_version) {
+	case txgbe_mbox_api_11:
+	case txgbe_mbox_api_12:
+	case txgbe_mbox_api_13:
+		break;
+	default:
+		return 0;
+	}
+
+	/* Fetch queue configuration from the PF */
+	msg[0] = TXGBE_VF_GET_QUEUES;
+	for (i = 1; i < 5; i++)
+		msg[i] = 0;
+
+	err = txgbevf_write_msg_read_ack(hw, msg, msg, 5);
+	if (!err) {
+		msg[0] &= ~TXGBE_VT_MSGTYPE_CTS;
+
+		/*
+		 * if we we didn't get an ACK there must have been
+		 * some sort of mailbox error so we should treat it
+		 * as such
+		 */
+		if (msg[0] != (TXGBE_VF_GET_QUEUES | TXGBE_VT_MSGTYPE_ACK))
+			return TXGBE_ERR_MBX;
+
+		/* record and validate values from message */
+		hw->mac.max_tx_queues = msg[TXGBE_VF_TX_QUEUES];
+		if (hw->mac.max_tx_queues == 0 ||
+		    hw->mac.max_tx_queues > TXGBE_VF_MAX_TX_QUEUES)
+			hw->mac.max_tx_queues = TXGBE_VF_MAX_TX_QUEUES;
+
+		hw->mac.max_rx_queues = msg[TXGBE_VF_RX_QUEUES];
+		if (hw->mac.max_rx_queues == 0 ||
+		    hw->mac.max_rx_queues > TXGBE_VF_MAX_RX_QUEUES)
+			hw->mac.max_rx_queues = TXGBE_VF_MAX_RX_QUEUES;
+
+		*num_tcs = msg[TXGBE_VF_TRANS_VLAN];
+		/* in case of unknown state assume we cannot tag frames */
+		if (*num_tcs > hw->mac.max_rx_queues)
+			*num_tcs = 1;
+
+		*default_tc = msg[TXGBE_VF_DEF_QUEUE];
+		/* default to queue 0 on out-of-bounds queue number */
+		if (*default_tc >= hw->mac.max_tx_queues)
+			*default_tc = 0;
+	}
+
+	return err;
+}
diff --git a/drivers/net/txgbe/base/txgbe_vf.h b/drivers/net/txgbe/base/txgbe_vf.h
new file mode 100644
index 000000000..70f90c262
--- /dev/null
+++ b/drivers/net/txgbe/base/txgbe_vf.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015-2020
+ */
+
+#ifndef _TXGBE_VF_H_
+#define _TXGBE_VF_H_
+
+#include "txgbe_type.h"
+
+#define TXGBE_VF_MAX_TX_QUEUES	8
+#define TXGBE_VF_MAX_RX_QUEUES	8
+
+s32 txgbe_init_ops_vf(struct txgbe_hw *hw);
+s32 txgbe_reset_hw_vf(struct txgbe_hw *hw);
+s32 txgbe_stop_hw_vf(struct txgbe_hw *hw);
+int txgbevf_negotiate_api_version(struct txgbe_hw *hw, int api);
+int txgbevf_get_queues(struct txgbe_hw *hw, unsigned int *num_tcs,
+		       unsigned int *default_tc);
+
+#endif /* __TXGBE_VF_H__ */
diff --git a/drivers/net/txgbe/txgbe_ethdev_vf.c b/drivers/net/txgbe/txgbe_ethdev_vf.c
index e5d0e1adf..a6bead4d1 100644
--- a/drivers/net/txgbe/txgbe_ethdev_vf.c
+++ b/drivers/net/txgbe/txgbe_ethdev_vf.c
@@ -17,6 +17,8 @@
 
 #define TXGBEVF_PMD_NAME "rte_txgbevf_pmd" /* PMD name */
 static int txgbevf_dev_close(struct rte_eth_dev *dev);
+static void txgbevf_intr_disable(struct rte_eth_dev *dev);
+static void txgbevf_intr_enable(struct rte_eth_dev *dev);
 
 /*
  * The set of PCI devices this driver supports (for VF)
@@ -29,14 +31,43 @@ static const struct rte_pci_id pci_id_txgbevf_map[] = {
 
 static const struct eth_dev_ops txgbevf_eth_dev_ops;
 
+/*
+ * Negotiate mailbox API version with the PF.
+ * After reset API version is always set to the basic one (txgbe_mbox_api_10).
+ * Then we try to negotiate starting with the most recent one.
+ * If all negotiation attempts fail, then we will proceed with
+ * the default one (txgbe_mbox_api_10).
+ */
+static void
+txgbevf_negotiate_api(struct txgbe_hw *hw)
+{
+	int32_t i;
+
+	/* start with highest supported, proceed down */
+	static const int sup_ver[] = {
+		txgbe_mbox_api_13,
+		txgbe_mbox_api_12,
+		txgbe_mbox_api_11,
+		txgbe_mbox_api_10,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(sup_ver); i++) {
+		if (txgbevf_negotiate_api_version(hw, sup_ver[i]) == 0)
+			break;
+	}
+}
+
 /*
  * Virtual Function device init
  */
 static int
 eth_txgbevf_dev_init(struct rte_eth_dev *eth_dev)
 {
+	int err;
+	uint32_t tc, tcs;
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
 	struct txgbe_hw *hw = TXGBE_DEV_HW(eth_dev);
+
 	PMD_INIT_FUNC_TRACE();
 
 	eth_dev->dev_ops = &txgbevf_eth_dev_ops;
@@ -73,6 +104,46 @@ eth_txgbevf_dev_init(struct rte_eth_dev *eth_dev)
 	hw->subsystem_vendor_id = pci_dev->id.subsystem_vendor_id;
 	hw->hw_addr = (void *)pci_dev->mem_resource[0].addr;
 
+	/* Initialize the shared code (base driver) */
+	err = txgbe_init_shared_code(hw);
+	if (err != 0) {
+		PMD_INIT_LOG(ERR,
+			"Shared code init failed for txgbevf: %d", err);
+		return -EIO;
+	}
+
+	/* init_mailbox_params */
+	hw->mbx.init_params(hw);
+
+	/* Disable the interrupts for VF */
+	txgbevf_intr_disable(eth_dev);
+
+	hw->mac.num_rar_entries = 128; /* The MAX of the underlying PF */
+	err = hw->mac.reset_hw(hw);
+
+	/*
+	 * The VF reset operation returns the TXGBE_ERR_INVALID_MAC_ADDR when
+	 * the underlying PF driver has not assigned a MAC address to the VF.
+	 * In this case, assign a random MAC address.
+	 */
+	if (err != 0 && err != TXGBE_ERR_INVALID_MAC_ADDR) {
+		PMD_INIT_LOG(ERR, "VF Initialization Failure: %d", err);
+		/*
+		 * This error code will be propagated to the app by
+		 * rte_eth_dev_reset, so use a public error code rather than
+		 * the internal-only TXGBE_ERR_RESET_FAILED
+		 */
+		return -EAGAIN;
+	}
+
+	/* negotiate mailbox API version to use with the PF. */
+	txgbevf_negotiate_api(hw);
+
+	/* Get Rx/Tx queue count via mailbox, which is ready after reset_hw */
+	txgbevf_get_queues(hw, &tcs, &tc);
+
+	txgbevf_intr_enable(eth_dev);
+
 	return 0;
 }
 
@@ -113,15 +184,59 @@ static struct rte_pci_driver rte_txgbevf_pmd = {
 	.remove = eth_txgbevf_pci_remove,
 };
 
+/*
+ * Virtual Function operations
+ */
+static void
+txgbevf_intr_disable(struct rte_eth_dev *dev)
+{
+	struct txgbe_interrupt *intr = TXGBE_DEV_INTR(dev);
+	struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+
+	PMD_INIT_FUNC_TRACE();
+
+	/* Clear interrupt mask to stop from interrupts being generated */
+	wr32(hw, TXGBE_VFIMS, TXGBE_VFIMS_MASK);
+
+	txgbe_flush(hw);
+
+	/* Clear mask value. */
+	intr->mask_misc = TXGBE_VFIMS_MASK;
+}
+
+static void
+txgbevf_intr_enable(struct rte_eth_dev *dev)
+{
+	struct txgbe_interrupt *intr = TXGBE_DEV_INTR(dev);
+	struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+
+	PMD_INIT_FUNC_TRACE();
+
+	/* VF enable interrupt autoclean */
+	wr32(hw, TXGBE_VFIMC, TXGBE_VFIMC_MASK);
+
+	txgbe_flush(hw);
+
+	intr->mask_misc = 0;
+}
+
 static int
 txgbevf_dev_close(struct rte_eth_dev *dev)
 {
+	struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
 	PMD_INIT_FUNC_TRACE();
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return 0;
 
+	hw->mac.reset_hw(hw);
+
+	txgbe_dev_free_queues(dev);
+
 	dev->dev_ops = NULL;
 
+	/* Disable the interrupts for VF */
+	txgbevf_intr_disable(dev);
+
 	return 0;
 }
 
-- 
2.27.0




  parent reply	other threads:[~2021-01-22  9:48 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-22  9:47 [dpdk-dev] [PATCH v1 00/20] net/txgbe: add VF driver support Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 01/20] net/txgbe: add ethdev probe and remove for VF device Jiawen Wu
2021-02-02 17:48   ` Ferruh Yigit
2021-01-22  9:47 ` Jiawen Wu [this message]
2021-02-02 17:51   ` [dpdk-dev] [PATCH v1 02/20] net/txgbe: add base code for VF driver Ferruh Yigit
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 03/20] net/txgbe: support add and remove VF device MAC address Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 04/20] net/txgbe: get VF device information Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 05/20] net/txgbe: add interrupt operation for VF device Jiawen Wu
2021-02-02 17:49   ` Ferruh Yigit
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 06/20] net/txgbe: get link status of " Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 07/20] net/txgbe: add Rx and Tx unit init for " Jiawen Wu
2021-02-02 17:49   ` Ferruh Yigit
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 08/20] net/txgbe: add VF device stats and xstats get operation Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 09/20] net/txgbe: add VLAN handle support to VF driver Jiawen Wu
2021-02-02 17:52   ` Ferruh Yigit
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 10/20] net/txgbe: add RSS support for VF device Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 11/20] net/txgbe: add VF device promiscuous and allmulticast mode Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 12/20] net/txgbe: support multicast MAC filter for VF driver Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 13/20] net/txgbe: support to update MTU on VF device Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 14/20] net/txgbe: support register dump " Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 15/20] net/txgbe: start and stop " Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 16/20] net/txgbe: add some supports as PF driver implemented Jiawen Wu
2021-02-02 17:50   ` Ferruh Yigit
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 17/20] net/txgbe: support VF representor Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 18/20] net/txgbe: hardware support for " Jiawen Wu
2021-02-02 17:50   ` Ferruh Yigit
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 19/20] net/txgbe: support VLAN filter " Jiawen Wu
2021-01-22  9:48 ` [dpdk-dev] [PATCH v1 20/20] doc: update release note for txgbe Jiawen Wu
2021-02-02 17:50   ` Ferruh Yigit
2021-02-02 18:07 ` [dpdk-dev] [PATCH v1 00/20] net/txgbe: add VF driver support Ferruh Yigit
2021-02-03  7:48   ` Jiawen Wu
2021-02-10 13:24     ` Ferruh Yigit

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=20210122094800.197748-3-jiawenwu@trustnetic.com \
    --to=jiawenwu@trustnetic.com \
    --cc=dev@dpdk.org \
    /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.