[v6,8/8] net/rnp handle device interrupts

Message ID 20230901023050.40893-9-caowenbo@mucse.com (mailing list archive)
State Changes Requested, archived
Delegated to: Ferruh Yigit
Headers
Series drivers/net Add Support mucse N10 Pmd Driver |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS
ci/github-robot: build success github build: passed
ci/iol-mellanox-Performance success Performance Testing PASS
ci/intel-Functional success Functional PASS
ci/iol-compile-amd64-testing success Testing PASS
ci/iol-unit-arm64-testing success Testing PASS
ci/iol-sample-apps-testing success Testing PASS
ci/iol-unit-amd64-testing success Testing PASS
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-compile-arm64-testing success Testing PASS

Commit Message

11 Sept. 1, 2023, 2:30 a.m. UTC
  Handle device lsc interrupt event

Signed-off-by: Wenbo Cao <caowenbo@mucse.com>
---
 drivers/net/rnp/base/rnp_hw.h       |   5 +
 drivers/net/rnp/base/rnp_mac_regs.h | 279 ++++++++++++++++++++++++++++
 drivers/net/rnp/rnp.h               |   8 +
 drivers/net/rnp/rnp_ethdev.c        |  17 ++
 drivers/net/rnp/rnp_mbx.h           |   3 +-
 drivers/net/rnp/rnp_mbx_fw.c        | 233 +++++++++++++++++++++++
 drivers/net/rnp/rnp_mbx_fw.h        |  38 +++-
 7 files changed, 580 insertions(+), 3 deletions(-)
 create mode 100644 drivers/net/rnp/base/rnp_mac_regs.h
  

Patch

diff --git a/drivers/net/rnp/base/rnp_hw.h b/drivers/net/rnp/base/rnp_hw.h
index 395b9d5c71..5c50484c6c 100644
--- a/drivers/net/rnp/base/rnp_hw.h
+++ b/drivers/net/rnp/base/rnp_hw.h
@@ -10,6 +10,7 @@ 
 #include "rnp_osdep.h"
 #include "rnp_dma_regs.h"
 #include "rnp_eth_regs.h"
+#include "rnp_mac_regs.h"
 #include "rnp_cfg.h"
 
 static inline unsigned int rnp_rd_reg(volatile void *addr)
@@ -48,6 +49,10 @@  static inline void rnp_wr_reg(volatile void *reg, int val)
 	rnp_eth_wr(hw, RNP_RAL_BASE_ADDR(hw_idx), val)
 #define RNP_MACADDR_UPDATE_HI(hw, hw_idx, val) \
 	rnp_eth_wr(hw, RNP_RAH_BASE_ADDR(hw_idx), val)
+#define rnp_mac_rd(hw, id, off) \
+	rnp_rd_reg((char *)(hw)->mac_base[id] + (off))
+#define rnp_mac_wr(hw, id, off, val) \
+	rnp_wr_reg((char *)(hw)->mac_base[id] + (off), val)
 struct rnp_hw;
 /* Mbx Operate info */
 enum MBX_ID {
diff --git a/drivers/net/rnp/base/rnp_mac_regs.h b/drivers/net/rnp/base/rnp_mac_regs.h
new file mode 100644
index 0000000000..f9466b3841
--- /dev/null
+++ b/drivers/net/rnp/base/rnp_mac_regs.h
@@ -0,0 +1,279 @@ 
+#ifndef __RNP_MAC_REGS_H__
+#define __RNP_MAC_REGS_H__
+
+#include "rnp_osdep.h"
+#define RNP_MAC_TX_CFG		(0x0)
+
+/* Transmitter Enable */
+#define RNP_MAC_TE			BIT(0)
+/* Jabber Disable */
+#define RNP_MAC_JD			BIT(16)
+#define RNP_SPEED_SEL_1G		(BIT(30) | BIT(29) | BIT(28))
+#define RNP_SPEED_SEL_10G		BIT(30)
+#define RNP_SPEED_SEL_40G		(0)
+#define RNP_MAC_RX_CFG			(0x4)
+/* Receiver Enable */
+#define RNP_MAC_RE			BIT(0)
+/* Automatic Pad or CRC Stripping */
+#define RNP_MAC_ACS			BIT(1)
+/* CRC stripping for Type packets */
+#define RNP_MAC_CST			BIT(2)
+/* Disable CRC Check */
+#define RNP_MAC_DCRCC			BIT(3)
+/* Enable Max Frame Size Limit */
+#define RNP_MAC_GPSLCE			BIT(6)
+/* Watchdog Disable */
+#define RNP_MAC_WD			BIT(7)
+/* Jumbo Packet Support En */
+#define RNP_MAC_JE			BIT(8)
+/* Loopback Mode */
+#define RNP_MAC_LM			BIT(10)
+/* Giant Packet Size Limit */
+#define RNP_MAC_GPSL_MASK		GENMASK(29, 16)
+#define RNP_MAC_MAX_GPSL		(1518)
+#define RNP_MAC_CPSL_SHIFT		(16)
+
+#define RNP_MAC_PKT_FLT_CTRL		(0x8)
+
+/* Receive All */
+#define RNP_MAC_RA			BIT(31)
+/* Pass Control Packets */
+#define RNP_MAC_PCF			GENMASK(7, 6)
+#define RNP_MAC_PCF_OFFSET		(6)
+/* Mac Filter ALL Ctrl Frame */
+#define RNP_MAC_PCF_FAC			(0)
+/* Mac Forward ALL Ctrl Frame Except Pause */
+#define RNP_MAC_PCF_NO_PAUSE		(1)
+/* Mac Forward All Ctrl Pkt */
+#define RNP_MAC_PCF_PA			(2)
+/* Mac Forward Ctrl Frame Match Unicast */
+#define RNP_MAC_PCF_PUN			(3)
+/* Promiscuous Mode */
+#define RNP_MAC_PROMISC_EN		BIT(0)
+/* Hash Unicast */
+#define RNP_MAC_HUC			BIT(1)
+/* Hash Multicast */
+#define RNP_MAC_HMC			BIT(2)
+/*  Pass All Multicast */
+#define RNP_MAC_PM			BIT(4)
+/* Disable Broadcast Packets */
+#define RNP_MAC_DBF			BIT(5)
+/* Hash or Perfect Filter */
+#define RNP_MAC_HPF			BIT(10)
+#define RNP_MAC_VTFE			BIT(16)
+/* Interrupt Status */
+#define RNP_MAC_INT_STATUS		_MAC_(0xb0)
+#define RNP_MAC_LS_MASK			GENMASK(25, 24)
+#define RNP_MAC_LS_UP			(0)
+#define RNP_MAC_LS_LOCAL_FAULT		BIT(25)
+#define RNP_MAC_LS_REMOTE_FAULT		(BIT(25) | BIT(24))
+/* Unicast Mac Hash Table */
+#define RNP_MAC_UC_HASH_TB(n)		_MAC_(0x10 + ((n) * 0x4))
+
+
+#define RNP_MAC_LPI_CTRL		(0xd0)
+
+/* PHY Link Status Disable */
+#define RNP_MAC_PLSDIS			BIT(18)
+/* PHY Link Status */
+#define RNP_MAC_PLS			BIT(17)
+
+/* MAC VLAN CTRL Strip REG */
+#define RNP_MAC_VLAN_TAG		(0x50)
+
+/* En Inner VLAN Strip Action */
+#define RNP_MAC_EIVLS			GENMASK(29, 28)
+/* Inner VLAN Strip Action Shift */
+#define RNP_MAC_IV_EIVLS_SHIFT		(28)
+/* Inner Vlan Don't Strip*/
+#define RNP_MAC_IV_STRIP_NONE		(0x0)
+/* Inner Vlan Strip When Filter Match Success */
+#define RNP_MAC_IV_STRIP_PASS		(0x1)
+/* Inner Vlan STRIP When Filter Match FAIL */
+#define RNP_MAC_IV_STRIP_FAIL		(0x2)
+/* Inner Vlan STRIP Always */
+#define RNP_MAC_IV_STRIP_ALL		(0X3)
+/* VLAN Strip Mode Ctrl Shift */
+#define RNP_VLAN_TAG_CTRL_EVLS_SHIFT	(21)
+/* En Double Vlan Processing */
+#define RNP_MAC_VLAN_EDVLP		BIT(26)
+/* VLAN Tag Hash Table Match Enable */
+#define RNP_MAC_VLAN_VTHM		BIT(25)
+/*  Enable VLAN Tag in Rx status */
+#define RNP_MAC_VLAN_EVLRXS		BIT(24)
+/* Disable VLAN Type Check */
+#define RNP_MAC_VLAN_DOVLTC		BIT(20)
+/* Enable S-VLAN */
+#define RNP_MAC_VLAN_ESVL		BIT(18)
+/* Enable 12-Bit VLAN Tag Comparison Filter */
+#define RNP_MAC_VLAN_ETV		BIT(16)
+#define RNP_MAC_VLAN_HASH_EN		GENMASK(15, 0)
+#define RNP_MAC_VLAN_VID		GENMASK(15, 0)
+/* VLAN Don't Strip */
+#define RNP_MAC_VLAN_STRIP_NONE		(0x0 << RNP_VLAN_TAG_CTRL_EVLS_SHIFT)
+/* VLAN Filter Success Then STRIP */
+#define RNP_MAC_VLAN_STRIP_PASS		(0x1 << RNP_VLAN_TAG_CTRL_EVLS_SHIFT)
+/* VLAN Filter Failed Then STRIP */
+#define RNP_MAC_VLAN_STRIP_FAIL		(0x2 << RNP_VLAN_TAG_CTRL_EVLS_SHIFT)
+/* All Vlan Will Strip */
+#define RNP_MAC_VLAN_STRIP_ALL		(0x3 << RNP_VLAN_TAG_CTRL_EVLS_SHIFT)
+
+#define RNP_MAC_VLAN_HASH_TB		(0x58)
+#define RNP_MAC_VLAN_HASH_MASK		GENMASK(15, 0)
+
+/* MAC VLAN CTRL INSERT REG */
+#define RNP_MAC_VLAN_INCL		(0x60)
+#define RNP_MAC_INVLAN_INCL		(0x64)
+
+/* VLAN Tag Input */
+/* VLAN_Tag Insert From Description */
+#define RNP_MAC_VLAN_VLTI		BIT(20)
+/* C-VLAN or S-VLAN */
+#define RNP_MAC_VLAN_CSVL		BIT(19)
+#define RNP_MAC_VLAN_INSERT_CVLAN	(0 << 19)
+#define RNP_MAC_VLAN_INSERT_SVLAN	(1 << 19)
+/* VLAN Tag Control in Transmit Packets */
+#define RNP_MAC_VLAN_VLC		GENMASK(17, 16)
+/* VLAN Tag Control Offset Bit */
+#define RNP_MAC_VLAN_VLC_SHIFT		(16)
+/* Don't Anything ON TX VLAN*/
+#define RNP_MAC_VLAN_VLC_NONE		(0x0 << RNP_MAC_VLAN_VLC_SHIFT)
+/* MAC Delete VLAN */
+#define RNP_MAC_VLAN_VLC_DEL		(0x1 << RNP_MAC_VLAN_VLC_SHIFT)
+/* MAC Add VLAN */
+#define RNP_MAC_VLAN_VLC_ADD		(0x2 << RNP_MAC_VLAN_VLC_SHIFT)
+/* MAC Replace VLAN */
+#define RNP_MAC_VLAN_VLC_REPLACE	(0x3 << RNP_MAC_VLAN_VLC_SHIFT)
+/* VLAN Tag for Transmit Packets For Insert/Remove */
+#define RNP_MAC_VLAN_VLT		GENMASK(15, 0)
+/* TX Peer TC Flow Ctrl */
+
+#define RNP_MAC_Q0_TX_FC(n)		(0x70 + ((n) * 0x4))
+
+/* Edit Pause Time */
+#define RNP_MAC_FC_PT			GENMASK(31, 16)
+#define RNP_MAC_FC_PT_OFFSET		(16)
+/*  Disable Zero-Quanta Pause */
+#define RNP_MAC_FC_DZPQ			BIT(7)
+/* Pause Low Threshold */
+#define RNP_MAC_FC_PLT			GENMASK(6, 4)
+#define RNP_MAC_FC_PLT_OFFSET		(4)
+#define RNP_MAC_FC_PLT_4_SLOT		(0)
+#define RNP_MAC_FC_PLT_28_SLOT		(1)
+#define RNP_MAC_FC_PLT_36_SLOT		(2)
+#define RNP_MAC_FC_PLT_144_SLOT		(3)
+#define RNP_MAC_FC_PLT_256_SLOT		(4)
+/* Transmit Flow Control Enable */
+#define RNP_MAC_FC_TEE			BIT(1)
+/* Transmit Flow Control Busy Immediately */
+#define RNP_MAC_FC_FCB			BIT(0)
+/* Mac RX Flow Ctrl*/
+
+#define RNP_MAC_RX_FC			(0x90)
+
+/* Rx Priority Based Flow Control Enable */
+#define RNP_MAC_RX_FC_PFCE		BIT(8)
+/* Unicast Pause Packet Detect */
+#define RNP_MAC_RX_FC_UP		BIT(1)
+/* Receive Flow Control Enable */
+#define RNP_MAC_RX_FC_RFE		BIT(0)
+
+/* Rx Mac Address Base */
+#define RNP_MAC_ADDR_DEF_HI		_MAC_(0x0300)
+
+#define RNP_MAC_AE			BIT(31)
+#define RNP_MAC_ADDR_LO(n)		_MAC_((0x0304) + ((n) * 0x8))
+#define RNP_MAC_ADDR_HI(n)		_MAC_((0x0300) + ((n) * 0x8))
+
+/* Mac Manage Counts */
+#define RNP_MMC_CTRL			_MAC_(0x0800)
+#define RNP_MMC_RSTONRD			BIT(2)
+/* Tx Good And Bad Bytes Base */
+#define RNP_MMC_TX_GBOCTGB		_MAC_(0x0814)
+/* Tx Good And Bad Frame Num Base */
+#define RNP_MMC_TX_GBFRMB		_MAC_(0x081c)
+/* Tx Good Broadcast Frame Num Base */
+#define RNP_MMC_TX_BCASTB		_MAC_(0x0824)
+/* Tx Good Multicast Frame Num Base */
+#define RNP_MMC_TX_MCASTB		_MAC_(0x082c)
+/* Tx 64Bytes Frame Num */
+#define RNP_MMC_TX_64_BYTESB		_MAC_(0x0834)
+#define RNP_MMC_TX_65TO127_BYTESB	_MAC_(0x083c)
+#define RNP_MMC_TX_128TO255_BYTEB	_MAC_(0x0844)
+#define RNP_MMC_TX_256TO511_BYTEB	_MAC_(0x084c)
+#define RNP_MMC_TX_512TO1023_BYTEB	_MAC_(0x0854)
+#define RNP_MMC_TX_1024TOMAX_BYTEB	_MAC_(0x085c)
+/* Tx Good And Bad Unicast Frame Num Base */
+#define RNP_MMC_TX_GBUCASTB		_MAC_(0x0864)
+/* Tx Good And Bad Multicast Frame Num Base */
+#define RNP_MMC_TX_GBMCASTB		_MAC_(0x086c)
+/* Tx Good And Bad Broadcast Frame NUM Base */
+#define RNP_MMC_TX_GBBCASTB		_MAC_(0x0874)
+/* Tx Frame Underflow Error */
+#define RNP_MMC_TX_UNDRFLWB		_MAC_(0x087c)
+/* Tx Good Frame Bytes Base */
+#define RNP_MMC_TX_GBYTESB		_MAC_(0x0884)
+/* Tx Good Frame Num Base*/
+#define RNP_MMC_TX_GBRMB		_MAC_(0x088c)
+/* Tx Good Pause Frame Num Base */
+#define RNP_MMC_TX_PAUSEB		_MAC_(0x0894)
+/* Tx Good Vlan Frame Num Base */
+#define RNP_MMC_TX_VLANB		_MAC_(0x089c)
+
+/* Rx Good And Bad Frames Num Base */
+#define RNP_MMC_RX_GBFRMB		_MAC_(0x0900)
+/* Rx Good And Bad Frames Bytes Base */
+#define RNP_MMC_RX_GBOCTGB		_MAC_(0x0908)
+/* Rx Good Framse Bytes Base */
+#define RNP_MMC_RX_GOCTGB		_MAC_(0x0910)
+/* Rx Good Broadcast Frames Num Base */
+#define RNP_MMC_RX_BCASTGB		_MAC_(0x0918)
+/* Rx Good Multicast Frames Num Base */
+#define RNP_MMC_RX_MCASTGB		_MAC_(0x0920)
+/* Rx Crc Error Frames Num Base */
+#define RNP_MMC_RX_CRCERB		_MAC_(0x0928)
+/* Rx Less Than 64Byes with Crc Err Base*/
+#define RNP_MMC_RX_RUNTERB		_MAC_(0x0930)
+/* Receive Jumbo Frame Error */
+#define RNP_MMC_RX_JABBER_ERR		_MAC_(0x0934)
+/* Shorter Than 64Bytes without Any Errora Base */
+#define RNP_MMC_RX_USIZEGB		_MAC_(0x0938)
+/* Len Oversize Than Support */
+#define RNP_MMC_RX_OSIZEGB		_MAC_(0x093c)
+/* Rx 64Byes Frame Num Base */
+#define RNP_MMC_RX_64_BYTESB		_MAC_(0x0940)
+/* Rx 65Bytes To 127Bytes Frame Num Base */
+#define RNP_MMC_RX_65TO127_BYTESB	_MAC_(0x0948)
+/* Rx 128Bytes To 255Bytes Frame Num Base */
+#define RNP_MMC_RX_128TO255_BYTESB	_MAC_(0x0950)
+/* Rx 256Bytes To 511Bytes Frame Num Base */
+#define RNP_MMC_RX_256TO511_BYTESB	_MAC_(0x0958)
+/* Rx 512Bytes To 1023Bytes Frame Num Base */
+#define RNP_MMC_RX_512TO1203_BYTESB	_MAC_(0x0960)
+/* Rx Len Bigger Than 1024Bytes Base */
+#define RNP_MMC_RX_1024TOMAX_BYTESB	_MAC_(0x0968)
+/* Rx Unicast Frame Good Num Base */
+#define RNP_MMC_RX_UCASTGB		_MAC_(0x0970)
+/* Rx Length Error Of Frame Part */
+#define RNP_MMC_RX_LENERRB		_MAC_(0x0978)
+/* Rx received with a Length field not equal to the valid frame size */
+#define RNP_MMC_RX_OUTOF_RANGE		_MAC_(0x0980)
+/* Rx Pause Frame Good Num Base */
+#define RNP_MMC_RX_PAUSEB		_MAC_(0x0988)
+/* Rx Vlan Frame Good Num Base */
+#define RNP_MMC_RX_VLANGB		_MAC_(0x0998)
+/* Rx With A Watchdog Timeout Err Frame Base */
+#define RNP_MMC_RX_WDOGERRB		_MAC_(0x09a0)
+
+/* 1588 */
+#define RNP_MAC_TS_CTRL                 _MAC_(0X0d00)
+#define RNP_MAC_SUB_SECOND_INCREMENT    _MAC_(0x0d04)
+#define RNP_MAC_SYS_TIME_SEC_CFG        _MAC_(0x0d08)
+#define RNP_MAC_SYS_TIME_NANOSEC_CFG    _MAC_(0x0d0c)
+#define RNP_MAC_SYS_TIME_SEC_UPDATE     _MAC_(0x0d10)
+#define RNP_MAC_SYS_TIME_NANOSEC_UPDATE _MAC_(0x0d14)
+#define RNP_MAC_TS_ADDEND               _MAC_(0x0d18)
+#define RNP_MAC_TS_STATS                _MAC_(0x0d20)
+#define RNP_MAC_INTERRUPT_ENABLE        _MAC_(0x00b4)
+
+#endif /* __RNP_MAC_REGS_H__ */
diff --git a/drivers/net/rnp/rnp.h b/drivers/net/rnp/rnp.h
index 7e797cf177..413c8b0a73 100644
--- a/drivers/net/rnp/rnp.h
+++ b/drivers/net/rnp/rnp.h
@@ -111,6 +111,8 @@  struct rnp_eth_port {
 	uint8_t tx_func_sec; /* force set io tx func */
 	struct rte_eth_dev *eth_dev;
 	struct rnp_port_attr attr;
+	uint64_t state;
+	rte_spinlock_t rx_mac_lock; /* Lock For Mac_cfg resource write */
 	/* Recvice Mac Address Record Table */
 	uint8_t mac_use_tb[RNP_MAX_MAC_ADDRS];
 	uint8_t use_num_mac;
@@ -131,6 +133,12 @@  enum {
 	RNP_IO_FUNC_USE_COMMON,
 };
 
+enum rnp_port_state {
+	RNP_PORT_STATE_PAUSE = 0,
+	RNP_PORT_STATE_FINISH,
+	RNP_PORT_STATE_SETTING,
+};
+
 struct rnp_eth_adapter {
 	enum rnp_work_mode mode;
 	enum rnp_resource_share_m s_mode; /* Port Resource Share Policy */
diff --git a/drivers/net/rnp/rnp_ethdev.c b/drivers/net/rnp/rnp_ethdev.c
index 131da42259..22adfbeabc 100644
--- a/drivers/net/rnp/rnp_ethdev.c
+++ b/drivers/net/rnp/rnp_ethdev.c
@@ -601,10 +601,23 @@  static int rnp_post_handle(struct rnp_eth_adapter *adapter)
 	return 0;
 }
 
+static void rnp_dev_interrupt_handler(void *param)
+{
+	struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
+	struct rnp_eth_adapter *adapter = RNP_DEV_TO_ADAPTER(dev);
+
+	rte_intr_disable(intr_handle);
+	rnp_fw_msg_handler(adapter);
+	rte_intr_enable(intr_handle);
+}
+
 static int
 rnp_eth_dev_init(struct rte_eth_dev *dev)
 {
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
 	struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
 	struct rnp_eth_adapter *adapter = NULL;
 	char name[RTE_ETH_NAME_MAX_LEN] = " ";
@@ -680,6 +693,10 @@  rnp_eth_dev_init(struct rte_eth_dev *dev)
 		rnp_mac_rx_disable(eth_dev);
 		rnp_mac_tx_disable(eth_dev);
 	}
+	rte_intr_disable(intr_handle);
+	/* Enable Link Update Event Interrupt */
+	rte_intr_callback_register(intr_handle,
+			rnp_dev_interrupt_handler, dev);
 	ret = rnp_post_handle(adapter);
 	if (ret)
 		goto eth_alloc_error;
diff --git a/drivers/net/rnp/rnp_mbx.h b/drivers/net/rnp/rnp_mbx.h
index 87949c1726..d6b78e32a7 100644
--- a/drivers/net/rnp/rnp_mbx.h
+++ b/drivers/net/rnp/rnp_mbx.h
@@ -13,7 +13,8 @@ 
 
 /* Mbx Ctrl state */
 #define RNP_VFMAILBOX_SIZE	(14) /* 16 32 bit words - 64 bytes */
-#define TSRN10_VFMBX_SIZE	(RNP_VFMAILBOX_SIZE)
+#define RNP_FW_MAILBOX_SIZE	RNP_VFMAILBOX_SIZE
+#define RNP_VFMBX_SIZE		(RNP_VFMAILBOX_SIZE)
 #define RNP_VT_MSGTYPE_ACK	(0x80000000)
 
 #define RNP_VT_MSGTYPE_NACK	(0x40000000)
diff --git a/drivers/net/rnp/rnp_mbx_fw.c b/drivers/net/rnp/rnp_mbx_fw.c
index 0c3f499cf2..a0a163e98c 100644
--- a/drivers/net/rnp/rnp_mbx_fw.c
+++ b/drivers/net/rnp/rnp_mbx_fw.c
@@ -545,3 +545,236 @@  int rnp_hw_set_fw_force_speed_1g(struct rte_eth_dev *dev, int enable)
 {
 	return rnp_mbx_set_dump(dev, 0x01150000 | (enable & 1));
 }
+
+static inline int
+rnp_mbx_fw_reply_handler(struct rnp_eth_adapter *adapter __rte_unused,
+			 struct mbx_fw_cmd_reply *reply)
+{
+	struct mbx_req_cookie *cookie;
+	/* dbg_here; */
+	cookie = reply->cookie;
+	if (!cookie || cookie->magic != COOKIE_MAGIC) {
+		RNP_PMD_LOG(ERR,
+				"[%s] invalid cookie:%p opcode: "
+				"0x%x v0:0x%x\n",
+				__func__,
+				cookie,
+				reply->opcode,
+				*((int *)reply));
+		return -EIO;
+	}
+
+	if (cookie->priv_len > 0)
+		memcpy(cookie->priv, reply->data, cookie->priv_len);
+
+	cookie->done = 1;
+
+	if (reply->flags & FLAGS_ERR)
+		cookie->errcode = reply->error_code;
+	else
+		cookie->errcode = 0;
+
+	return 0;
+}
+
+void rnp_link_stat_mark(struct rnp_hw *hw, int nr_lane, int up)
+{
+	u32 v;
+
+	rte_spinlock_lock(&hw->fw_lock);
+	v = rnp_rd_reg(hw->link_sync);
+	v &= ~(0xffff0000);
+	v |= 0xa5a40000;
+	if (up)
+		v |= BIT(nr_lane);
+	else
+		v &= ~BIT(nr_lane);
+	rnp_wr_reg(hw->link_sync, v);
+
+	rte_spinlock_unlock(&hw->fw_lock);
+}
+
+void rnp_link_report(struct rte_eth_dev *dev, bool link_en)
+{
+	struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
+	struct rnp_hw *hw = RNP_DEV_TO_HW(dev);
+	struct rte_eth_link link;
+
+	link.link_duplex = link_en ? port->attr.phy_meta.link_duplex :
+		RTE_ETH_LINK_FULL_DUPLEX;
+	link.link_status = link_en ? RTE_ETH_LINK_UP : RTE_ETH_LINK_DOWN;
+	link.link_speed = link_en ? port->attr.speed :
+		RTE_ETH_SPEED_NUM_UNKNOWN;
+	RNP_PMD_LOG(INFO,
+			"\nPF[%d]link changed: changed_lane:0x%x, "
+			"status:0x%x\n",
+			hw->pf_vf_num & RNP_PF_NB_MASK ? 1 : 0,
+			port->attr.nr_port,
+			link_en);
+	link.link_autoneg = port->attr.phy_meta.link_autoneg
+		? RTE_ETH_LINK_SPEED_AUTONEG
+		: RTE_ETH_LINK_SPEED_FIXED;
+	/* Report Link Info To Upper Firmwork */
+	rte_eth_linkstatus_set(dev, &link);
+	/* Notice Event Process Link Status Change */
+	rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
+	/* Notce Firmware LSC Event SW Received */
+	rnp_link_stat_mark(hw, port->attr.nr_port, link_en);
+}
+
+static void rnp_dev_alarm_link_handler(void *param)
+{
+	struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
+	struct rnp_eth_port *port = RNP_DEV_TO_PORT(dev);
+	uint32_t status;
+
+	status = port->attr.link_ready;
+	rnp_link_report(dev, status);
+}
+
+static void rnp_link_event(struct rnp_eth_adapter *adapter,
+			   struct mbx_fw_cmd_req *req)
+{
+	struct rnp_hw *hw = &adapter->hw;
+	struct rnp_eth_port *port;
+	bool link_change = false;
+	uint32_t lane_bit;
+	uint32_t sync_bit;
+	uint32_t link_en;
+	uint32_t ctrl;
+	int i;
+
+	for (i = 0; i < adapter->num_ports; i++) {
+		port = adapter->ports[i];
+		if (port == NULL)
+			continue;
+		link_change = false;
+		lane_bit = port->attr.nr_port;
+		if (__atomic_load_n(&port->state, __ATOMIC_RELAXED)
+				!= RNP_PORT_STATE_FINISH)
+			continue;
+		if (!(BIT(lane_bit) & req->link_stat.changed_lanes))
+			continue;
+		link_en = BIT(lane_bit) & req->link_stat.lane_status;
+		sync_bit = BIT(lane_bit) & rnp_rd_reg(hw->link_sync);
+
+		if (link_en) {
+			/* Port Link Change To Up */
+			if (!port->attr.link_ready) {
+				link_change = true;
+				port->attr.link_ready = true;
+			}
+			if (req->link_stat.port_st_magic == SPEED_VALID_MAGIC) {
+				port->attr.speed = req->link_stat.st[lane_bit].speed;
+				port->attr.phy_meta.link_duplex =
+					req->link_stat.st[lane_bit].duplex;
+				port->attr.phy_meta.link_autoneg =
+					req->link_stat.st[lane_bit].autoneg;
+				RNP_PMD_INIT_LOG(INFO,
+						"phy_id %d speed %d duplex "
+						"%d issgmii %d PortID %d\n",
+						req->link_stat.st[lane_bit].phy_addr,
+						req->link_stat.st[lane_bit].speed,
+						req->link_stat.st[lane_bit].duplex,
+						req->link_stat.st[lane_bit].is_sgmii,
+						port->attr.rte_pid);
+			}
+		} else {
+			/* Port Link to Down */
+			if (port->attr.link_ready) {
+				link_change = true;
+				port->attr.link_ready = false;
+			}
+		}
+		if (link_change || sync_bit != link_en) {
+			/* WorkAround For Hardware When Link Down
+			 * Eth Module Tx-side Can't Drop In some condition
+			 * So back The Packet To Rx Side To Drop Packet
+			 */
+			/* To Protect Conflict Hw Resource */
+			rte_spinlock_lock(&port->rx_mac_lock);
+			ctrl = rnp_mac_rd(hw, lane_bit, RNP_MAC_RX_CFG);
+			if (port->attr.link_ready) {
+				ctrl &= ~RNP_MAC_LM;
+				rnp_eth_wr(hw,
+					RNP_RX_FIFO_FULL_THRETH(lane_bit),
+					RNP_RX_DEFAULT_VAL);
+			} else {
+				rnp_eth_wr(hw,
+					RNP_RX_FIFO_FULL_THRETH(lane_bit),
+					RNP_RX_WORKAROUND_VAL);
+				ctrl |= RNP_MAC_LM;
+			}
+			rnp_mac_wr(hw, lane_bit, RNP_MAC_RX_CFG, ctrl);
+			rte_spinlock_unlock(&port->rx_mac_lock);
+			rte_eal_alarm_set(RNP_ALARM_INTERVAL,
+					rnp_dev_alarm_link_handler,
+					(void *)port->eth_dev);
+		}
+	}
+}
+
+static inline int
+rnp_mbx_fw_req_handler(struct rnp_eth_adapter *adapter,
+		       struct mbx_fw_cmd_req *req)
+{
+	switch (req->opcode) {
+	case LINK_STATUS_EVENT:
+		rnp_link_event(adapter, req);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static inline int rnp_rcv_msg_from_fw(struct rnp_eth_adapter *adapter)
+{
+	const struct rnp_mbx_api *ops = RNP_DEV_TO_MBX_OPS(adapter->eth_dev);
+	struct rnp_hw *hw = &adapter->hw;
+	u32 msgbuf[RNP_FW_MAILBOX_SIZE];
+	uint16_t check_state;
+	int retval;
+
+	retval = ops->read(hw, msgbuf, RNP_FW_MAILBOX_SIZE, MBX_FW);
+	if (retval) {
+		PMD_DRV_LOG(ERR, "Error receiving message from FW\n");
+		return retval;
+	}
+#define RNP_MBX_SYNC_MASK GENMASK(15, 0)
+
+	check_state = msgbuf[0] & RNP_MBX_SYNC_MASK;
+	/* this is a message we already processed, do nothing */
+	if (check_state & FLAGS_DD)
+		return rnp_mbx_fw_reply_handler(adapter,
+				(struct mbx_fw_cmd_reply *)msgbuf);
+	else
+		return rnp_mbx_fw_req_handler(adapter,
+				(struct mbx_fw_cmd_req *)msgbuf);
+
+	return 0;
+}
+
+static void rnp_rcv_ack_from_fw(struct rnp_eth_adapter *adapter)
+{
+	struct rnp_hw *hw __rte_unused = &adapter->hw;
+	u32 msg __rte_unused = RNP_VT_MSGTYPE_NACK;
+	/* do-nothing */
+}
+
+int rnp_fw_msg_handler(struct rnp_eth_adapter *adapter)
+{
+	const struct rnp_mbx_api *ops = RNP_DEV_TO_MBX_OPS(adapter->eth_dev);
+	struct rnp_hw *hw = &adapter->hw;
+
+	/* == check cpureq */
+	if (!ops->check_for_msg(hw, MBX_FW))
+		rnp_rcv_msg_from_fw(adapter);
+
+	/* process any acks */
+	if (!ops->check_for_ack(hw, MBX_FW))
+		rnp_rcv_ack_from_fw(adapter);
+
+	return 0;
+}
diff --git a/drivers/net/rnp/rnp_mbx_fw.h b/drivers/net/rnp/rnp_mbx_fw.h
index 39fb0f6ef3..e0174c1d22 100644
--- a/drivers/net/rnp/rnp_mbx_fw.h
+++ b/drivers/net/rnp/rnp_mbx_fw.h
@@ -32,6 +32,8 @@  enum GENERIC_CMD {
 	GET_PHY_ABALITY = 0x0601,
 	GET_MAC_ADDRESS = 0x0602,
 	RESET_PHY = 0x0603,
+	GET_LINK_STATUS = 0x0607,
+	LINK_STATUS_EVENT = 0x0608,
 	GET_LANE_STATUS = 0x0610,
 	SET_EVENT_MASK = 0x0613,
 	 /* fw update */
@@ -98,6 +100,21 @@  struct phy_abilities {
 	};
 } __rte_packed __rte_aligned(4);
 
+struct port_stat {
+	u8 phy_addr;		/* Phy MDIO address */
+
+	u8 duplex          : 1; /* FIBRE is always 1,Twisted Pair 1 or 0 */
+	u8 autoneg         : 1; /* autoned state */
+	u8 fec             : 1;
+	u8 an_rev          : 1;
+	u8 link_traing     : 1;
+	u8 is_sgmii        : 1; /* avild fw >= 0.5.0.17 */
+	u16 speed;		/* cur port linked speed */
+
+	u16 pause : 4;
+	u16 rev   : 12;
+} __rte_packed;
+
 #define RNP_SPEED_CAP_UNKNOWN    (0)
 #define RNP_SPEED_CAP_10M_FULL   BIT(2)
 #define RNP_SPEED_CAP_100M_FULL  BIT(3)
@@ -186,8 +203,14 @@  struct mbx_fw_cmd_reply {
 		struct phy_abilities phy_abilities;
 	};
 } __rte_packed __rte_aligned(4);
-
-#define MBX_REQ_HDR_LEN            24
+/* == flags == */
+#define FLAGS_DD	BIT(0) /* driver clear 0, FW must set 1 */
+#define FLAGS_CMP	BIT(1) /* driver clear 0, FW mucst set */
+/* driver clear 0, FW must set only if it reporting an error */
+#define FLAGS_ERR	BIT(2)
+
+#define MBX_REQ_HDR_LEN		(24)
+#define RNP_ALARM_INTERVAL	(50000) /* unit us */
 /* driver -> firmware */
 struct mbx_fw_cmd_req {
 	unsigned short flags;     /* 0-1 */
@@ -240,6 +263,14 @@  struct mbx_fw_cmd_req {
 			int flag;
 			int nr_lane;
 		} set_dump;
+
+		struct {
+			unsigned short changed_lanes;
+			unsigned short lane_status;
+			unsigned int port_st_magic;
+#define SPEED_VALID_MAGIC 0xa4a6a8a9
+			struct port_stat st[4];
+		} link_stat; /* FW->RC */
 	};
 } __rte_packed __rte_aligned(4);
 
@@ -364,4 +395,7 @@  int rnp_mbx_get_lane_stat(struct rte_eth_dev *dev);
 int rnp_fw_update(struct rnp_eth_adapter *adapter);
 int rnp_hw_set_fw_10g_1g_auto_detch(struct rte_eth_dev *dev, int enable);
 int rnp_hw_set_fw_force_speed_1g(struct rte_eth_dev *dev, int enable);
+void rnp_link_stat_mark(struct rnp_hw *hw, int nr_lane, int up);
+void rnp_link_report(struct rte_eth_dev *dev, bool link_en);
+int rnp_fw_msg_handler(struct rnp_eth_adapter *adapter);
 #endif /* __RNP_MBX_FW_H__*/