Handle device lsc interrupt event

Signed-off-by: Wenbo Cao <caowe...@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

diff --git a/drivers/net/rnp/base/rnp_hw.h b/drivers/net/rnp/base/rnp_hw.h
index 7b7584959e..a8a253b766 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)
@@ -35,6 +36,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..bfe7e1d780
--- /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_REMOT_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 Stip */
+#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 Boradcast 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)
+/* Recive 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 029e8a2776..77551b1f6f 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 fbcfc4f661..d72e53c999 100644
--- a/drivers/net/rnp/rnp_ethdev.c
+++ b/drivers/net/rnp/rnp_ethdev.c
@@ -600,10 +600,23 @@ static int rnp_post_handle(struct rnp_eth_adapter 
*adapter)
        return 0;
 }
 
+static void rnp_dev_interrupt_handler(void *parm)
+{
+       struct rte_eth_dev *dev = (struct rte_eth_dev *)parm;
+       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] = " ";
@@ -679,6 +692,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)
diff --git a/drivers/net/rnp/rnp_mbx.h b/drivers/net/rnp/rnp_mbx.h
index ee020b5fbc..ccd127c276 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 eda1389364..48f88811a0 100644
--- a/drivers/net/rnp/rnp_mbx_fw.c
+++ b/drivers/net/rnp/rnp_mbx_fw.c
@@ -546,3 +546,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)
+{
+       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)
+{
+       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 cc45a572cc..086b13c10d 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_ADDRES = 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 linke 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__*/
-- 
2.27.0

Reply via email to