From: Jie Liu <liujie5@linkdatatechnology.com>
To: stephen@networkplumber.org
Cc: dev@dpdk.org, Jie Liu <liujie5@linkdatatechnology.com>
Subject: [PATCH v10 13/14] net/sxe: add virtual function
Date: Sat, 19 Jul 2025 17:05:36 +0800 [thread overview]
Message-ID: <20250719090537.699357-13-liujie5@linkdatatechnology.com> (raw)
In-Reply-To: <20250719090537.699357-1-liujie5@linkdatatechnology.com>
Add virtual function.
Signed-off-by: Jie Liu <liujie5@linkdatatechnology.com>
---
drivers/net/sxe/base/sxe_queue_common.c | 4 +
drivers/net/sxe/base/sxevf_hw.c | 951 +++++++++++++++
drivers/net/sxe/base/sxevf_hw.h | 349 ++++++
drivers/net/sxe/base/sxevf_regs.h | 119 ++
drivers/net/sxe/meson.build | 37 +-
drivers/net/sxe/pf/rte_pmd_sxe.h | 4 +-
drivers/net/sxe/pf/sxe.h | 5 +-
drivers/net/sxe/pf/sxe_filter.c | 177 +++
drivers/net/sxe/pf/sxe_filter.h | 15 +
drivers/net/sxe/pf/sxe_main.c | 2 +
drivers/net/sxe/pf/sxe_phy.h | 1 +
drivers/net/sxe/pf/sxe_stats.c | 9 +-
drivers/net/sxe/pf/sxe_vf.c | 1427 +++++++++++++++++++++++
drivers/net/sxe/pf/sxe_vf.h | 219 ++++
drivers/net/sxe/sxe_testpmd.c | 130 +++
drivers/net/sxe/vf/sxevf.h | 43 +
drivers/net/sxe/vf/sxevf_ethdev.c | 768 ++++++++++++
drivers/net/sxe/vf/sxevf_ethdev.h | 16 +
drivers/net/sxe/vf/sxevf_filter.c | 493 ++++++++
drivers/net/sxe/vf/sxevf_filter.h | 70 ++
drivers/net/sxe/vf/sxevf_irq.c | 434 +++++++
drivers/net/sxe/vf/sxevf_irq.h | 35 +
drivers/net/sxe/vf/sxevf_main.c | 83 ++
drivers/net/sxe/vf/sxevf_msg.c | 624 ++++++++++
drivers/net/sxe/vf/sxevf_msg.h | 201 ++++
drivers/net/sxe/vf/sxevf_offload.c | 31 +
drivers/net/sxe/vf/sxevf_offload.h | 16 +
drivers/net/sxe/vf/sxevf_queue.c | 210 ++++
drivers/net/sxe/vf/sxevf_queue.h | 70 ++
drivers/net/sxe/vf/sxevf_rx.c | 163 +++
drivers/net/sxe/vf/sxevf_rx.h | 18 +
drivers/net/sxe/vf/sxevf_stats.c | 162 +++
drivers/net/sxe/vf/sxevf_stats.h | 31 +
drivers/net/sxe/vf/sxevf_tx.c | 46 +
drivers/net/sxe/vf/sxevf_tx.h | 14 +
35 files changed, 6958 insertions(+), 19 deletions(-)
create mode 100644 drivers/net/sxe/base/sxevf_hw.c
create mode 100644 drivers/net/sxe/base/sxevf_hw.h
create mode 100644 drivers/net/sxe/base/sxevf_regs.h
create mode 100644 drivers/net/sxe/pf/sxe_vf.c
create mode 100644 drivers/net/sxe/pf/sxe_vf.h
create mode 100644 drivers/net/sxe/vf/sxevf.h
create mode 100644 drivers/net/sxe/vf/sxevf_ethdev.c
create mode 100644 drivers/net/sxe/vf/sxevf_ethdev.h
create mode 100644 drivers/net/sxe/vf/sxevf_filter.c
create mode 100644 drivers/net/sxe/vf/sxevf_filter.h
create mode 100644 drivers/net/sxe/vf/sxevf_irq.c
create mode 100644 drivers/net/sxe/vf/sxevf_irq.h
create mode 100644 drivers/net/sxe/vf/sxevf_main.c
create mode 100644 drivers/net/sxe/vf/sxevf_msg.c
create mode 100644 drivers/net/sxe/vf/sxevf_msg.h
create mode 100644 drivers/net/sxe/vf/sxevf_offload.c
create mode 100644 drivers/net/sxe/vf/sxevf_offload.h
create mode 100644 drivers/net/sxe/vf/sxevf_queue.c
create mode 100644 drivers/net/sxe/vf/sxevf_queue.h
create mode 100644 drivers/net/sxe/vf/sxevf_rx.c
create mode 100644 drivers/net/sxe/vf/sxevf_rx.h
create mode 100644 drivers/net/sxe/vf/sxevf_stats.c
create mode 100644 drivers/net/sxe/vf/sxevf_stats.h
create mode 100644 drivers/net/sxe/vf/sxevf_tx.c
create mode 100644 drivers/net/sxe/vf/sxevf_tx.h
diff --git a/drivers/net/sxe/base/sxe_queue_common.c b/drivers/net/sxe/base/sxe_queue_common.c
index 978e56e98b..914718769f 100644
--- a/drivers/net/sxe/base/sxe_queue_common.c
+++ b/drivers/net/sxe/base/sxe_queue_common.c
@@ -13,11 +13,15 @@
#include "sxe_tx.h"
#include "sxe_logs.h"
#include "sxe_regs.h"
+#include "sxevf_regs.h"
#include "sxe.h"
#if defined SXE_DPDK_L4_FEATURES && defined SXE_DPDK_SIMD
#include "sxe_vec_common.h"
#include <rte_vect.h>
#endif
+#if defined SXE_DPDK_L4_FEATURES && defined SXE_DPDK_SRIOV
+#include "sxevf.h"
+#endif
#include "sxe_queue_common.h"
#include "sxe_queue.h"
diff --git a/drivers/net/sxe/base/sxevf_hw.c b/drivers/net/sxe/base/sxevf_hw.c
new file mode 100644
index 0000000000..7425bafedb
--- /dev/null
+++ b/drivers/net/sxe/base/sxevf_hw.c
@@ -0,0 +1,951 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+#if defined(__KERNEL__) || defined(SXE_KERNEL_TEST)
+#include <linux/etherdevice.h>
+
+#include "sxevf_hw.h"
+#include "sxevf_regs.h"
+#include "sxe_log.h"
+#include "sxevf_irq.h"
+#include "sxevf_msg.h"
+#include "sxevf_ring.h"
+#include "sxevf.h"
+#include "sxevf_rx_proc.h"
+#else
+#include "sxe_errno.h"
+#include "sxe_logs.h"
+#include "sxe_dpdk_version.h"
+#include "sxe_compat_version.h"
+#include "sxevf.h"
+#include "sxevf_hw.h"
+#endif
+
+#if defined SXE_DPDK_L4_FEATURES && defined SXE_DPDK_SRIOV
+struct sxevf_adapter;
+#endif
+
+#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL << (n)) - 1))
+#define DMA_MASK_NONE 0x0ULL
+
+#define SXEVF_REG_READ_CNT 5
+
+#define SXE_REG_READ_FAIL 0xffffffffU
+
+#define SXEVF_RING_WAIT_LOOP (100)
+#define SXEVF_MAX_RX_DESC_POLL (10)
+
+
+#define SXEVF_REG_READ(hw, addr) sxevf_reg_read(hw, addr)
+#define SXEVF_REG_WRITE(hw, reg, value) sxevf_reg_write(hw, reg, value)
+#define SXEVF_WRITE_FLUSH(a) sxevf_reg_read(a, SXE_VFSTATUS)
+
+#ifndef SXE_DPDK
+void sxevf_hw_fault_handle(struct sxevf_hw *hw)
+{
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ if (test_bit(SXEVF_HW_FAULT, &hw->state))
+ return;
+
+ set_bit(SXEVF_HW_FAULT, &hw->state);
+
+ LOG_DEV_ERR("sxe nic hw fault");
+
+ if (hw->fault_handle != NULL && hw->priv != NULL)
+ hw->fault_handle(hw->priv);
+}
+
+static void sxevf_hw_fault_check(struct sxevf_hw *hw, u32 reg)
+{
+ u32 value;
+ u8 __iomem *base_addr = hw->reg_base_addr;
+ struct sxevf_adapter *adapter = hw->adapter;
+ u8 i;
+
+ if (reg == SXE_VFSTATUS)
+ sxevf_hw_fault_handle(hw);
+
+
+ for (i = 0; i < SXEVF_REG_READ_CNT; i++) {
+ value = hw->reg_read(base_addr + SXE_VFSTATUS);
+
+ if (value != SXEVF_REG_READ_FAIL)
+ break;
+
+ mdelay(20);
+ }
+
+ LOG_INFO_BDF("retry done i:%d value:0x%x", i, value);
+
+ if (value == SXEVF_REG_READ_FAIL)
+ sxevf_hw_fault_handle(hw);
+}
+
+static u32 sxevf_reg_read(struct sxevf_hw *hw, u32 reg)
+{
+ u32 value;
+ u8 __iomem *base_addr = hw->reg_base_addr;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ if (sxevf_is_hw_fault(hw)) {
+ value = SXEVF_REG_READ_FAIL;
+ goto l_ret;
+ }
+
+ value = hw->reg_read(base_addr + reg);
+ if (unlikely(value == SXEVF_REG_READ_FAIL)) {
+ LOG_ERROR_BDF("reg[0x%x] read failed, value=%#x", reg, value);
+ sxevf_hw_fault_check(hw, reg);
+ }
+
+l_ret:
+ return value;
+}
+
+static void sxevf_reg_write(struct sxevf_hw *hw, u32 reg, u32 value)
+{
+ u8 __iomem *base_addr = hw->reg_base_addr;
+
+ if (sxevf_is_hw_fault(hw))
+ return;
+
+ hw->reg_write(value, base_addr + reg);
+}
+
+#else
+
+static u32 sxevf_reg_read(struct sxevf_hw *hw, u32 reg)
+{
+ u32 i, value;
+ u8 __iomem *base_addr = hw->reg_base_addr;
+
+ value = rte_le_to_cpu_32(rte_read32(base_addr + reg));
+ if (unlikely(value == SXEVF_REG_READ_FAIL)) {
+ for (i = 0; i < SXEVF_REG_READ_CNT; i++) {
+ LOG_ERROR("reg[0x%x] read failed, value=%#x",
+ reg, value);
+ value = rte_le_to_cpu_32(rte_read32(base_addr + reg));
+ if (value != SXEVF_REG_READ_FAIL) {
+ LOG_INFO("reg[0x%x] read ok, value=%#x",
+ reg, value);
+ break;
+ }
+
+ mdelay(3);
+ }
+ }
+
+ return value;
+}
+
+static void sxevf_reg_write(struct sxevf_hw *hw, u32 reg, u32 value)
+{
+ u8 __iomem *base_addr = hw->reg_base_addr;
+
+ rte_write32((rte_cpu_to_le_32(value)), (base_addr + reg));
+}
+#endif
+
+void sxevf_hw_stop(struct sxevf_hw *hw)
+{
+ u8 i;
+ u32 value;
+
+ for (i = 0; i < SXEVF_TXRX_RING_NUM_MAX; i++) {
+ value = SXEVF_REG_READ(hw, SXE_VFRXDCTL(i));
+ if (value & SXE_VFRXDCTL_ENABLE) {
+ value &= ~SXE_VFRXDCTL_ENABLE;
+ SXEVF_REG_WRITE(hw, SXE_VFRXDCTL(i), value);
+ }
+ }
+
+ SXEVF_WRITE_FLUSH(hw);
+
+ SXEVF_REG_WRITE(hw, SXE_VFEIMC, SXEVF_VFEIMC_IRQ_MASK);
+ SXEVF_REG_READ(hw, SXE_VFEICR);
+
+ for (i = 0; i < SXEVF_TXRX_RING_NUM_MAX; i++) {
+ value = SXEVF_REG_READ(hw, SXE_VFTXDCTL(i));
+ if (value & SXE_VFTXDCTL_ENABLE) {
+ value &= ~SXE_VFTXDCTL_ENABLE;
+ SXEVF_REG_WRITE(hw, SXE_VFTXDCTL(i), value);
+ }
+ }
+}
+
+void sxevf_msg_write(struct sxevf_hw *hw, u8 index, u32 msg)
+{
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ SXEVF_REG_WRITE(hw, SXE_VFMBMEM + (index << 2), msg);
+
+ LOG_DEBUG_BDF("index:%u write mbx mem:0x%x.", index, msg);
+}
+
+u32 sxevf_msg_read(struct sxevf_hw *hw, u8 index)
+{
+ u32 value = SXEVF_REG_READ(hw, SXE_VFMBMEM + (index << 2));
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ LOG_DEBUG_BDF("index:%u read mbx mem:0x%x.", index, value);
+
+ return value;
+}
+
+u32 sxevf_mailbox_read(struct sxevf_hw *hw)
+{
+ return SXEVF_REG_READ(hw, SXE_VFMAILBOX);
+}
+
+void sxevf_mailbox_write(struct sxevf_hw *hw, u32 value)
+{
+ SXEVF_REG_WRITE(hw, SXE_VFMAILBOX, value);
+}
+
+void sxevf_pf_req_irq_trigger(struct sxevf_hw *hw)
+{
+ SXEVF_REG_WRITE(hw, SXE_VFMAILBOX, SXE_VFMAILBOX_REQ);
+}
+
+void sxevf_pf_ack_irq_trigger(struct sxevf_hw *hw)
+{
+ SXEVF_REG_WRITE(hw, SXE_VFMAILBOX, SXE_VFMAILBOX_ACK);
+}
+
+void sxevf_event_irq_map(struct sxevf_hw *hw, u16 vector)
+{
+ u8 allocation;
+ u32 ivar;
+
+ allocation = vector | SXEVF_IVAR_ALLOC_VALID;
+
+ ivar = SXEVF_REG_READ(hw, SXE_VFIVAR_MISC);
+ ivar &= ~0xFF;
+ ivar |= allocation;
+
+ SXEVF_REG_WRITE(hw, SXE_VFIVAR_MISC, ivar);
+}
+
+void sxevf_specific_irq_enable(struct sxevf_hw *hw, u32 value)
+{
+ SXEVF_REG_WRITE(hw, SXE_VFEIMS, value);
+}
+
+void sxevf_irq_enable(struct sxevf_hw *hw, u32 mask)
+{
+ SXEVF_REG_WRITE(hw, SXE_VFEIAM, mask);
+ SXEVF_REG_WRITE(hw, SXE_VFEIMS, mask);
+}
+
+void sxevf_irq_disable(struct sxevf_hw *hw)
+{
+ SXEVF_REG_WRITE(hw, SXE_VFEIAM, 0);
+ SXEVF_REG_WRITE(hw, SXE_VFEIMC, ~0);
+
+ SXEVF_WRITE_FLUSH(hw);
+}
+
+void sxevf_hw_ring_irq_map(struct sxevf_hw *hw, bool is_tx, u16 hw_ring_idx, u16 vector)
+{
+ u8 allocation;
+ u32 ivar, position;
+
+ allocation = vector | SXEVF_IVAR_ALLOC_VALID;
+
+ position = ((hw_ring_idx & 1) * 16) + (8 * is_tx);
+
+ ivar = SXEVF_REG_READ(hw, SXE_VFIVAR(hw_ring_idx >> 1));
+ ivar &= ~(0xFF << position);
+ ivar |= (allocation << position);
+
+ SXEVF_REG_WRITE(hw, SXE_VFIVAR(hw_ring_idx >> 1), ivar);
+}
+
+void sxevf_ring_irq_interval_set(struct sxevf_hw *hw, u16 irq_idx, u32 interval)
+{
+ u32 eitr = interval & SXEVF_EITR_ITR_MASK;
+
+ eitr |= SXEVF_EITR_CNT_WDIS;
+
+ SXEVF_REG_WRITE(hw, SXE_VFEITR(irq_idx), eitr);
+}
+
+static void sxevf_event_irq_interval_set(struct sxevf_hw *hw, u16 irq_idx, u32 value)
+{
+ SXEVF_REG_WRITE(hw, SXE_VFEITR(irq_idx), value);
+}
+
+static void sxevf_pending_irq_clear(struct sxevf_hw *hw)
+{
+ SXEVF_REG_READ(hw, SXE_VFEICR);
+}
+
+static void sxevf_ring_irq_trigger(struct sxevf_hw *hw, u64 eics)
+{
+ SXEVF_REG_WRITE(hw, SXE_VFEICS, eics);
+}
+
+static const struct sxevf_irq_operations sxevf_irq_ops = {
+ .ring_irq_interval_set = sxevf_ring_irq_interval_set,
+ .event_irq_interval_set = sxevf_event_irq_interval_set,
+ .ring_irq_map = sxevf_hw_ring_irq_map,
+ .event_irq_map = sxevf_event_irq_map,
+ .pending_irq_clear = sxevf_pending_irq_clear,
+ .ring_irq_trigger = sxevf_ring_irq_trigger,
+ .specific_irq_enable = sxevf_specific_irq_enable,
+ .irq_enable = sxevf_irq_enable,
+ .irq_disable = sxevf_irq_disable,
+};
+
+void sxevf_hw_reset(struct sxevf_hw *hw)
+{
+ SXEVF_REG_WRITE(hw, SXE_VFCTRL, SXE_VFCTRL_RST);
+ SXEVF_WRITE_FLUSH(hw);
+}
+
+static bool sxevf_hw_rst_done(struct sxevf_hw *hw)
+{
+ return !(SXEVF_REG_READ(hw, SXE_VFCTRL) & SXE_VFCTRL_RST);
+}
+
+u32 sxevf_link_state_get(struct sxevf_hw *hw)
+{
+ return SXEVF_REG_READ(hw, SXE_VFLINKS);
+}
+
+u32 dump_regs[] = {
+ SXE_VFCTRL,
+};
+
+u16 sxevf_reg_dump_num_get(void)
+{
+ return ARRAY_SIZE(dump_regs);
+}
+
+static u32 sxevf_reg_dump(struct sxevf_hw *hw, u32 *regs_buff, u32 buf_size)
+{
+ u32 i;
+ u32 regs_num = buf_size / sizeof(u32);
+
+ for (i = 0; i < regs_num; i++)
+ regs_buff[i] = SXEVF_REG_READ(hw, dump_regs[i]);
+
+ return i;
+}
+
+#define PATTERN_TEST 1
+#define SET_READ_TEST 2
+#define WRITE_NO_TEST 3
+#define TABLE32_TEST 4
+#define TABLE64_TEST_LO 5
+#define TABLE64_TEST_HI 6
+
+struct sxevf_self_test_reg {
+ u32 reg;
+ u8 array_len;
+ u8 test_type;
+ u32 mask;
+ u32 write;
+};
+
+static const struct sxevf_self_test_reg self_test_reg[] = {
+ { SXE_VFRDBAL(0), 2, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 },
+ { SXE_VFRDBAH(0), 2, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+ { SXE_VFRDLEN(0), 2, PATTERN_TEST, 0x000FFFFF, 0x000FFFFF },
+ { SXE_VFRXDCTL(0), 2, WRITE_NO_TEST, 0, SXEVF_RXDCTL_ENABLE },
+ { SXE_VFRDT(0), 2, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
+ { SXE_VFRXDCTL(0), 2, WRITE_NO_TEST, 0, 0 },
+ { SXE_VFTDBAL(0), 2, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFFFF },
+ { SXE_VFTDBAH(0), 2, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
+ { SXE_VFTDLEN(0), 2, PATTERN_TEST, 0x000FFF80, 0x000FFF80 },
+ { .reg = 0 }
+};
+
+static s32 sxevf_reg_pattern_test(struct sxevf_hw *hw, u32 reg,
+ u32 mask, u32 write)
+{
+ s32 ret = 0;
+ u32 pat, val, before;
+ static const u32 test_pattern[] = {
+ 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFE};
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ if (sxevf_is_hw_fault(hw)) {
+ LOG_ERROR_BDF("hw fault");
+ ret = -SXEVF_DIAG_TEST_BLOCKED;
+ goto l_end;
+ }
+
+ for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) {
+ before = SXEVF_REG_READ(hw, reg);
+
+ SXEVF_REG_WRITE(hw, reg, test_pattern[pat] & write);
+ val = SXEVF_REG_READ(hw, reg);
+ if (val != (test_pattern[pat] & write & mask)) {
+ LOG_MSG_ERR(drv, "pattern test reg %04X failed: "
+ "got 0x%08X expected 0x%08X",
+ reg, val, (test_pattern[pat] & write & mask));
+ SXEVF_REG_WRITE(hw, reg, before);
+ ret = -SXEVF_DIAG_REG_PATTERN_TEST_ERR;
+ goto l_end;
+ }
+
+ SXEVF_REG_WRITE(hw, reg, before);
+ }
+
+l_end:
+ return ret;
+}
+
+static s32 sxevf_reg_set_and_check(struct sxevf_hw *hw, int reg,
+ u32 mask, u32 write)
+{
+ s32 ret = 0;
+ u32 val, before;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ if (sxevf_is_hw_fault(hw)) {
+ LOG_ERROR_BDF("hw fault");
+ ret = -SXEVF_DIAG_TEST_BLOCKED;
+ goto l_end;
+ }
+
+ before = SXEVF_REG_READ(hw, reg);
+ SXEVF_REG_WRITE(hw, reg, write & mask);
+ val = SXEVF_REG_READ(hw, reg);
+ if ((write & mask) != (val & mask)) {
+ LOG_DEV_ERR("set/check reg %04X test failed: "
+ "got 0x%08X expected 0x%08X",
+ reg, (val & mask), (write & mask));
+ SXEVF_REG_WRITE(hw, reg, before);
+ ret = -SXEVF_DIAG_CHECK_REG_TEST_ERR;
+ goto l_end;
+ }
+
+ SXEVF_REG_WRITE(hw, reg, before);
+
+l_end:
+ return ret;
+}
+
+static s32 sxevf_regs_test(struct sxevf_hw *hw)
+{
+ u32 i;
+ s32 ret = 0;
+ const struct sxevf_self_test_reg *test = self_test_reg;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ while (test->reg) {
+ for (i = 0; i < test->array_len; i++) {
+ switch (test->test_type) {
+ case PATTERN_TEST:
+ ret = sxevf_reg_pattern_test(hw,
+ test->reg + (i * 0x40),
+ test->mask, test->write);
+ break;
+ case TABLE32_TEST:
+ ret = sxevf_reg_pattern_test(hw,
+ test->reg + (i * 4),
+ test->mask, test->write);
+ break;
+ case TABLE64_TEST_LO:
+ ret = sxevf_reg_pattern_test(hw,
+ test->reg + (i * 8),
+ test->mask, test->write);
+ break;
+ case TABLE64_TEST_HI:
+ ret = sxevf_reg_pattern_test(hw,
+ (test->reg + 4) + (i * 8),
+ test->mask, test->write);
+ break;
+ case SET_READ_TEST:
+ ret = sxevf_reg_set_and_check(hw,
+ test->reg + (i * 0x40),
+ test->mask, test->write);
+ break;
+ case WRITE_NO_TEST:
+ SXEVF_REG_WRITE(hw, test->reg + (i * 0x40),
+ test->write);
+ break;
+ default:
+ LOG_ERROR_BDF("reg test mod err, type=%d",
+ test->test_type);
+ break;
+ }
+
+ if (ret)
+ goto l_end;
+ }
+ test++;
+ }
+
+l_end:
+ return ret;
+}
+
+static const struct sxevf_setup_operations sxevf_setup_ops = {
+ .reset = sxevf_hw_reset,
+ .hw_stop = sxevf_hw_stop,
+ .regs_test = sxevf_regs_test,
+ .regs_dump = sxevf_reg_dump,
+ .link_state_get = sxevf_link_state_get,
+ .reset_done = sxevf_hw_rst_done,
+};
+
+static void sxevf_tx_ring_desc_configure(struct sxevf_hw *hw, u32 desc_mem_len,
+ u64 desc_dma_addr, u8 reg_idx)
+{
+ SXEVF_REG_WRITE(hw, SXEVF_TDBAL(reg_idx), (desc_dma_addr &
+ DMA_BIT_MASK(32)));
+ SXEVF_REG_WRITE(hw, SXEVF_TDBAH(reg_idx), (desc_dma_addr >> 32));
+ SXEVF_REG_WRITE(hw, SXEVF_TDLEN(reg_idx), desc_mem_len);
+ SXEVF_REG_WRITE(hw, SXEVF_TDH(reg_idx), 0);
+ SXEVF_REG_WRITE(hw, SXEVF_TDT(reg_idx), 0);
+}
+
+static void sxevf_tx_writeback_off(struct sxevf_hw *hw, u8 reg_idx)
+{
+ SXEVF_REG_WRITE(hw, SXEVF_TDWBAH(reg_idx), 0);
+ SXEVF_REG_WRITE(hw, SXEVF_TDWBAL(reg_idx), 0);
+}
+
+static void sxevf_tx_desc_thresh_set(struct sxevf_hw *hw,
+ u8 reg_idx,
+ u32 wb_thresh,
+ u32 host_thresh,
+ u32 prefech_thresh)
+{
+ u32 txdctl = 0;
+
+ txdctl |= (wb_thresh << SXEVF_TXDCTL_WTHRESH_SHIFT);
+ txdctl |= (host_thresh << SXEVF_TXDCTL_HTHRESH_SHIFT) |
+ prefech_thresh;
+
+ SXEVF_REG_WRITE(hw, SXEVF_TXDCTL(reg_idx), txdctl);
+}
+
+void sxevf_tx_ring_switch(struct sxevf_hw *hw, u8 reg_idx, bool is_on)
+{
+ u32 wait_loop = SXEVF_MAX_TXRX_DESC_POLL;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ u32 txdctl = SXEVF_REG_READ(hw, SXEVF_TXDCTL(reg_idx));
+ if (is_on) {
+ txdctl |= SXEVF_TXDCTL_ENABLE;
+ SXEVF_REG_WRITE(hw, SXEVF_TXDCTL(reg_idx), txdctl);
+
+ do {
+ usleep_range(1000, 2000);
+ txdctl = SXEVF_REG_READ(hw, SXEVF_TXDCTL(reg_idx));
+ } while (--wait_loop && !(txdctl & SXEVF_TXDCTL_ENABLE));
+ } else {
+ txdctl &= ~SXEVF_TXDCTL_ENABLE;
+ SXEVF_REG_WRITE(hw, SXEVF_TXDCTL(reg_idx), txdctl);
+
+ do {
+ usleep_range(1000, 2000);
+ txdctl = SXEVF_REG_READ(hw, SXEVF_TXDCTL(reg_idx));
+ } while (--wait_loop && (txdctl & SXEVF_TXDCTL_ENABLE));
+ }
+
+ if (!wait_loop) {
+ LOG_DEV_ERR("tx ring %u switch %u failed within "
+ "the polling period", reg_idx, is_on);
+ }
+}
+
+static void sxevf_rx_disable(struct sxevf_hw *hw, u8 reg_idx)
+{
+ u32 rxdctl;
+ u32 wait_loop = SXEVF_RX_RING_POLL_MAX;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ if (!hw->reg_base_addr)
+ return;
+
+ rxdctl = SXEVF_REG_READ(hw, SXE_VFRXDCTL(reg_idx));
+ rxdctl &= ~SXE_VFRXDCTL_ENABLE;
+ SXEVF_REG_WRITE(hw, SXE_VFRXDCTL(reg_idx), rxdctl);
+
+ do {
+ sxe_udelay(10);
+ rxdctl = SXEVF_REG_READ(hw, SXE_VFRXDCTL(reg_idx));
+ } while (--wait_loop && (rxdctl & SXE_VFRXDCTL_ENABLE));
+
+ if (!wait_loop) {
+ LOG_ERROR_BDF("RXDCTL.ENABLE queue %d not cleared while polling",
+ reg_idx);
+ }
+}
+
+void sxevf_rx_ring_switch(struct sxevf_hw *hw, u8 reg_idx, bool is_on)
+{
+ u32 rxdctl;
+ u32 wait_loop = SXEVF_RING_WAIT_LOOP;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ rxdctl = SXEVF_REG_READ(hw, SXE_VFRXDCTL(reg_idx));
+ if (is_on) {
+ rxdctl |= SXEVF_RXDCTL_ENABLE | SXEVF_RXDCTL_VME;
+ SXEVF_REG_WRITE(hw, SXE_VFRXDCTL(reg_idx), rxdctl);
+
+ do {
+ usleep_range(1000, 2000);
+ rxdctl = SXEVF_REG_READ(hw, SXE_VFRXDCTL(reg_idx));
+ } while (--wait_loop && !(rxdctl & SXEVF_RXDCTL_ENABLE));
+ } else {
+ rxdctl &= ~SXEVF_RXDCTL_ENABLE;
+ SXEVF_REG_WRITE(hw, SXE_VFRXDCTL(reg_idx), rxdctl);
+
+ do {
+ usleep_range(1000, 2000);
+ rxdctl = SXEVF_REG_READ(hw, SXE_VFRXDCTL(reg_idx));
+ } while (--wait_loop && (rxdctl & SXEVF_RXDCTL_ENABLE));
+ }
+
+ SXEVF_WRITE_FLUSH(hw);
+
+ if (!wait_loop) {
+ LOG_DEV_ERR("rx ring %u switch %u failed within "
+ "the polling period", reg_idx, is_on);
+ }
+}
+
+void sxevf_rx_ring_desc_configure(struct sxevf_hw *hw, u32 desc_mem_len,
+ u64 desc_dma_addr, u8 reg_idx)
+{
+ SXEVF_REG_WRITE(hw, SXE_VFRDBAL(reg_idx),
+ (desc_dma_addr & DMA_BIT_MASK(32)));
+ SXEVF_REG_WRITE(hw, SXE_VFRDBAH(reg_idx), (desc_dma_addr >> 32));
+ SXEVF_REG_WRITE(hw, SXE_VFRDLEN(reg_idx), desc_mem_len);
+
+ SXEVF_WRITE_FLUSH(hw);
+
+ SXEVF_REG_WRITE(hw, SXE_VFRDH(reg_idx), 0);
+ SXEVF_REG_WRITE(hw, SXE_VFRDT(reg_idx), 0);
+}
+
+void sxevf_rx_rcv_ctl_configure(struct sxevf_hw *hw, u8 reg_idx,
+ u32 header_buf_len, u32 pkg_buf_len, bool drop_en)
+{
+ u32 srrctl = 0;
+
+ if (drop_en)
+ srrctl = SXEVF_SRRCTL_DROP_EN;
+
+ srrctl |= ((header_buf_len << SXEVF_SRRCTL_BSIZEHDRSIZE_SHIFT) &
+ SXEVF_SRRCTL_BSIZEHDR_MASK);
+ srrctl |= ((pkg_buf_len >> SXEVF_SRRCTL_BSIZEPKT_SHIFT) &
+ SXEVF_SRRCTL_BSIZEPKT_MASK);
+
+ SXEVF_REG_WRITE(hw, SXE_VFSRRCTL(reg_idx), srrctl);
+}
+
+static void sxevf_tx_ring_info_get(struct sxevf_hw *hw,
+ u8 idx, u32 *head, u32 *tail)
+{
+ *head = SXEVF_REG_READ(hw, SXE_VFTDH(idx));
+ *tail = SXEVF_REG_READ(hw, SXE_VFTDT(idx));
+}
+
+static const struct sxevf_dma_operations sxevf_dma_ops = {
+ .tx_ring_desc_configure = sxevf_tx_ring_desc_configure,
+ .tx_writeback_off = sxevf_tx_writeback_off,
+ .tx_desc_thresh_set = sxevf_tx_desc_thresh_set,
+ .tx_ring_switch = sxevf_tx_ring_switch,
+ .tx_ring_info_get = sxevf_tx_ring_info_get,
+
+ .rx_disable = sxevf_rx_disable,
+ .rx_ring_switch = sxevf_rx_ring_switch,
+ .rx_ring_desc_configure = sxevf_rx_ring_desc_configure,
+ .rx_rcv_ctl_configure = sxevf_rx_rcv_ctl_configure,
+};
+
+#ifdef SXE_DPDK
+#define SXEVF_32BIT_COUNTER_UPDATE(reg, last, cur) \
+ { \
+ u32 latest = SXEVF_REG_READ(hw, reg); \
+ (cur) += (latest - (last)) & UINT_MAX; \
+ last = latest; \
+ }
+
+#define SXEVF_36BIT_COUNTER_UPDATE(lsb, msb, last, cur) \
+ { \
+ u64 new_lsb = SXEVF_REG_READ(hw, lsb); \
+ u64 new_msb = SXEVF_REG_READ(hw, msb); \
+ u64 latest = ((new_msb << 32) | new_lsb); \
+ (cur) += (0x1000000000LL + latest - (last)) & 0xFFFFFFFFFLL; \
+ last = latest; \
+ }
+
+#else
+#define SXEVF_32BIT_COUNTER_UPDATE(reg, last_counter, counter) \
+ { \
+ u32 current_counter = SXEVF_REG_READ(hw, reg); \
+ if (current_counter < (last_counter)) \
+ (counter) += 0x100000000LL; \
+ last_counter = current_counter; \
+ (counter) &= 0xFFFFFFFF00000000LL; \
+ (counter) |= current_counter; \
+ }
+
+#define SXEVF_36BIT_COUNTER_UPDATE(reg_lsb, reg_msb, last_counter, counter) \
+ { \
+ u64 current_counter_lsb = SXEVF_REG_READ(hw, reg_lsb); \
+ u64 current_counter_msb = SXEVF_REG_READ(hw, reg_msb); \
+ u64 current_counter = (current_counter_msb << 32) | \
+ current_counter_lsb; \
+ if (current_counter < (last_counter)) \
+ (counter) += 0x1000000000LL; \
+ last_counter = current_counter; \
+ (counter) &= 0xFFFFFFF000000000LL; \
+ (counter) |= current_counter; \
+ }
+#endif
+
+void sxevf_packet_stats_get(struct sxevf_hw *hw,
+ struct sxevf_hw_stats *stats)
+{
+ SXEVF_32BIT_COUNTER_UPDATE(SXEVF_VFGPRC, stats->last_vfgprc,
+ stats->vfgprc);
+ SXEVF_32BIT_COUNTER_UPDATE(SXEVF_VFGPTC, stats->last_vfgptc,
+ stats->vfgptc);
+ SXEVF_36BIT_COUNTER_UPDATE(SXEVF_VFGORC_LSB, SXEVF_VFGORC_MSB,
+ stats->last_vfgorc,
+ stats->vfgorc);
+ SXEVF_36BIT_COUNTER_UPDATE(SXEVF_VFGOTC_LSB, SXEVF_VFGOTC_MSB,
+ stats->last_vfgotc,
+ stats->vfgotc);
+ SXEVF_32BIT_COUNTER_UPDATE(SXEVF_VFMPRC, stats->last_vfmprc,
+ stats->vfmprc);
+}
+
+void sxevf_stats_init_value_get(struct sxevf_hw *hw,
+ struct sxevf_hw_stats *stats)
+{
+ stats->last_vfgprc = SXEVF_REG_READ(hw, SXE_VFGPRC);
+ stats->last_vfgorc = SXEVF_REG_READ(hw, SXE_VFGORC_LSB);
+ stats->last_vfgorc |= (((u64)(SXEVF_REG_READ(hw, SXE_VFGORC_MSB))) << 32);
+ stats->last_vfgptc = SXEVF_REG_READ(hw, SXE_VFGPTC);
+ stats->last_vfgotc = SXEVF_REG_READ(hw, SXE_VFGOTC_LSB);
+ stats->last_vfgotc |= (((u64)(SXEVF_REG_READ(hw, SXE_VFGOTC_MSB))) << 32);
+ stats->last_vfmprc = SXEVF_REG_READ(hw, SXE_VFMPRC);
+}
+static const struct sxevf_stat_operations sxevf_stat_ops = {
+ .packet_stats_get = sxevf_packet_stats_get,
+ .stats_init_value_get = sxevf_stats_init_value_get,
+};
+
+static void sxevf_rx_max_used_ring_set(struct sxevf_hw *hw, u16 max_rx_ring)
+{
+ u32 rqpl = 0;
+
+ if (max_rx_ring > 1)
+ rqpl |= BIT(29);
+
+ SXEVF_REG_WRITE(hw, SXE_VFPSRTYPE, rqpl);
+}
+
+static const struct sxevf_dbu_operations sxevf_dbu_ops = {
+ .rx_max_used_ring_set = sxevf_rx_max_used_ring_set,
+};
+
+static const struct sxevf_mbx_operations sxevf_mbx_ops = {
+ .mailbox_read = sxevf_mailbox_read,
+ .mailbox_write = sxevf_mailbox_write,
+
+ .msg_write = sxevf_msg_write,
+ .msg_read = sxevf_msg_read,
+
+ .pf_req_irq_trigger = sxevf_pf_req_irq_trigger,
+ .pf_ack_irq_trigger = sxevf_pf_ack_irq_trigger,
+};
+
+void sxevf_hw_ops_init(struct sxevf_hw *hw)
+{
+ hw->setup.ops = &sxevf_setup_ops;
+ hw->irq.ops = &sxevf_irq_ops;
+ hw->mbx.ops = &sxevf_mbx_ops;
+ hw->dma.ops = &sxevf_dma_ops;
+ hw->stat.ops = &sxevf_stat_ops;
+ hw->dbu.ops = &sxevf_dbu_ops;
+}
+
+#ifdef SXE_DPDK
+
+#define SXEVF_RSS_FIELD_MASK 0xffff0000
+#define SXEVF_MRQC_RSSEN 0x00000001
+
+#define SXEVF_RSS_KEY_SIZE (40)
+#define SXEVF_MAX_RSS_KEY_ENTRIES (10)
+#define SXEVF_MAX_RETA_ENTRIES (128)
+
+void sxevf_rxtx_reg_init(struct sxevf_hw *hw)
+{
+ int i;
+ u32 vfsrrctl;
+
+ vfsrrctl = 0x100 << SXEVF_SRRCTL_BSIZEHDRSIZE_SHIFT;
+ vfsrrctl |= 0x800 >> SXEVF_SRRCTL_BSIZEPKT_SHIFT;
+
+ SXEVF_REG_WRITE(hw, SXE_VFPSRTYPE, 0);
+
+ for (i = 0; i < 7; i++) {
+ SXEVF_REG_WRITE(hw, SXE_VFRDH(i), 0);
+ SXEVF_REG_WRITE(hw, SXE_VFRDT(i), 0);
+ SXEVF_REG_WRITE(hw, SXE_VFRXDCTL(i), 0);
+ SXEVF_REG_WRITE(hw, SXE_VFSRRCTL(i), vfsrrctl);
+ SXEVF_REG_WRITE(hw, SXE_VFTDH(i), 0);
+ SXEVF_REG_WRITE(hw, SXE_VFTDT(i), 0);
+ SXEVF_REG_WRITE(hw, SXE_VFTXDCTL(i), 0);
+ SXEVF_REG_WRITE(hw, SXE_VFTDWBAH(i), 0);
+ SXEVF_REG_WRITE(hw, SXE_VFTDWBAL(i), 0);
+ }
+
+ SXEVF_WRITE_FLUSH(hw);
+}
+
+u32 sxevf_irq_cause_get(struct sxevf_hw *hw)
+{
+ return SXEVF_REG_READ(hw, SXE_VFEICR);
+}
+
+void sxevf_tx_desc_configure(struct sxevf_hw *hw, u32 desc_mem_len,
+ u64 desc_dma_addr, u8 reg_idx)
+{
+ SXEVF_REG_WRITE(hw, SXEVF_TDBAL(reg_idx), (desc_dma_addr &
+ DMA_BIT_MASK(32)));
+ SXEVF_REG_WRITE(hw, SXEVF_TDBAH(reg_idx), (desc_dma_addr >> 32));
+ SXEVF_REG_WRITE(hw, SXEVF_TDLEN(reg_idx), desc_mem_len);
+ SXEVF_REG_WRITE(hw, SXEVF_TDH(reg_idx), 0);
+ SXEVF_REG_WRITE(hw, SXEVF_TDT(reg_idx), 0);
+}
+
+void sxevf_rss_bit_num_set(struct sxevf_hw *hw, u32 value)
+{
+ SXEVF_REG_WRITE(hw, SXE_VFPSRTYPE, value);
+}
+
+void sxevf_hw_vlan_tag_strip_switch(struct sxevf_hw *hw,
+ u16 reg_index, bool is_enable)
+{
+ u32 vlnctrl;
+
+ vlnctrl = SXEVF_REG_READ(hw, SXE_VFRXDCTL(reg_index));
+
+ if (is_enable)
+ vlnctrl |= SXEVF_RXDCTL_VME;
+ else
+ vlnctrl &= ~SXEVF_RXDCTL_VME;
+
+ SXEVF_REG_WRITE(hw, SXE_VFRXDCTL(reg_index), vlnctrl);
+}
+
+void sxevf_tx_queue_thresh_set(struct sxevf_hw *hw, u8 reg_idx,
+ u32 prefech_thresh, u32 host_thresh, u32 wb_thresh)
+{
+ u32 txdctl = SXEVF_REG_READ(hw, SXEVF_TXDCTL(reg_idx));
+
+ txdctl |= (prefech_thresh & SXEVF_TXDCTL_THRESH_MASK);
+ txdctl |= ((host_thresh & SXEVF_TXDCTL_THRESH_MASK) << SXEVF_TXDCTL_HTHRESH_SHIFT);
+ txdctl |= ((wb_thresh & SXEVF_TXDCTL_THRESH_MASK) << SXEVF_TXDCTL_WTHRESH_SHIFT);
+
+ SXEVF_REG_WRITE(hw, SXEVF_TXDCTL(reg_idx), txdctl);
+}
+
+void sxevf_rx_desc_tail_set(struct sxevf_hw *hw, u8 reg_idx, u32 value)
+{
+ SXEVF_REG_WRITE(hw, SXE_VFRDT(reg_idx), value);
+}
+
+u32 sxevf_hw_rss_redir_tbl_get(struct sxevf_hw *hw, u16 reg_idx)
+{
+ return SXEVF_REG_READ(hw, SXE_VFRETA(reg_idx >> 2));
+}
+
+void sxevf_hw_rss_redir_tbl_set(struct sxevf_hw *hw,
+ u16 reg_idx, u32 value)
+{
+ SXEVF_REG_WRITE(hw, SXE_VFRETA(reg_idx >> 2), value);
+}
+
+u32 sxevf_hw_rss_key_get(struct sxevf_hw *hw, u8 reg_idx)
+{
+ u32 rss_key;
+
+ if (reg_idx >= SXEVF_MAX_RSS_KEY_ENTRIES)
+ rss_key = 0;
+ else
+ rss_key = SXEVF_REG_READ(hw, SXE_VFRSSRK(reg_idx));
+
+ return rss_key;
+}
+
+u32 sxevf_hw_rss_field_get(struct sxevf_hw *hw)
+{
+ u32 mrqc = SXEVF_REG_READ(hw, SXE_VFMRQC);
+ return (mrqc & SXEVF_RSS_FIELD_MASK);
+}
+
+bool sxevf_hw_is_rss_enabled(struct sxevf_hw *hw)
+{
+ bool rss_enable = false;
+ u32 mrqc = SXEVF_REG_READ(hw, SXE_VFMRQC);
+ if (mrqc & SXEVF_MRQC_RSSEN)
+ rss_enable = true;
+
+ return rss_enable;
+}
+
+void sxevf_hw_rss_key_set_all(struct sxevf_hw *hw, u32 *rss_key)
+{
+ u32 i;
+
+ for (i = 0; i < SXEVF_MAX_RSS_KEY_ENTRIES; i++)
+ SXEVF_REG_WRITE(hw, SXE_VFRSSRK(i), rss_key[i]);
+}
+
+void sxevf_hw_rss_cap_switch(struct sxevf_hw *hw, bool is_on)
+{
+ u32 mrqc = SXEVF_REG_READ(hw, SXE_VFMRQC);
+ if (is_on)
+ mrqc |= SXEVF_MRQC_RSSEN;
+ else
+ mrqc &= ~SXEVF_MRQC_RSSEN;
+
+ SXEVF_REG_WRITE(hw, SXE_VFMRQC, mrqc);
+}
+
+void sxevf_hw_rss_field_set(struct sxevf_hw *hw, u32 rss_field)
+{
+ u32 mrqc = SXEVF_REG_READ(hw, SXE_VFMRQC);
+
+ mrqc &= ~SXEVF_RSS_FIELD_MASK;
+ mrqc |= rss_field;
+ SXEVF_REG_WRITE(hw, SXE_VFMRQC, mrqc);
+}
+
+u32 sxevf_hw_regs_group_read(struct sxevf_hw *hw,
+ const struct sxevf_reg_info *regs,
+ u32 *reg_buf)
+{
+ u32 j, i = 0;
+ int count = 0;
+
+ while (regs[i].count) {
+ for (j = 0; j < regs[i].count; j++) {
+ reg_buf[count + j] = SXEVF_REG_READ(hw,
+ regs[i].addr + j * regs[i].stride);
+ LOG_INFO("regs= %s, regs_addr=%x, regs_value=%04x",
+ regs[i].name, regs[i].addr, reg_buf[count + j]);
+ }
+
+ i++;
+ count += j;
+ }
+
+ return count;
+};
+
+#endif
diff --git a/drivers/net/sxe/base/sxevf_hw.h b/drivers/net/sxe/base/sxevf_hw.h
new file mode 100644
index 0000000000..ede6238c0c
--- /dev/null
+++ b/drivers/net/sxe/base/sxevf_hw.h
@@ -0,0 +1,349 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#ifndef __SXEVF_HW_H__
+#define __SXEVF_HW_H__
+
+#if defined(__KERNEL__) || defined(SXE_KERNEL_TEST)
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/if_ether.h>
+#else
+#include "sxe_compat_platform.h"
+#ifdef SXE_HOST_DRIVER
+#include "sxe_drv_type.h"
+#endif
+#endif
+
+#include "sxevf_regs.h"
+
+#if defined(__KERNEL__) || defined(SXE_KERNEL_TEST)
+#define SXE_PRIU64 "llu"
+#define SXE_PRIX64 "llx"
+#define SXE_PRID64 "lld"
+#else
+#define SXE_PRIU64 PRIu64
+#define SXE_PRIX64 PRIx64
+#define SXE_PRID64 PRId64
+#endif
+
+#define SXEVF_TXRX_RING_NUM_MAX 8
+#define SXEVF_MAX_TXRX_DESC_POLL (10)
+#define SXEVF_TX_DESC_PREFETCH_THRESH_32 (32)
+#define SXEVF_TX_DESC_HOST_THRESH_1 (1)
+#define SXEVF_TX_DESC_WRITEBACK_THRESH_8 (8)
+#define SXEVF_TXDCTL_HTHRESH_SHIFT (8)
+#define SXEVF_TXDCTL_WTHRESH_SHIFT (16)
+
+#define SXEVF_TXDCTL_THRESH_MASK (0x7F)
+
+#define SXEVF_RX_RING_POLL_MAX (10)
+
+#define SXEVF_MAC_HDR_LEN_MAX (127)
+#define SXEVF_NETWORK_HDR_LEN_MAX (511)
+
+#define SXEVF_LINK_SPEED_UNKNOWN 0
+#define SXEVF_LINK_SPEED_1GB_FULL 0x0020
+#define SXEVF_LINK_SPEED_10GB_FULL 0x0080
+#define SXEVF_LINK_SPEED_100_FULL 0x0008
+
+#define SXEVF_VFT_TBL_SIZE (128)
+#define SXEVF_HW_TXRX_RING_NUM_MAX (128)
+
+#define SXEVF_VLAN_TAG_SIZE (4)
+
+#define SXEVF_HW_UC_ENTRY_NUM_MAX 128
+
+enum {
+ SXEVF_LINK_TO_PHY = 0,
+ SXEVF_LINK_TO_DOWN,
+ SXEVF_LINK_TO_REINIT,
+};
+
+enum {
+ SXEVF_DIAG_TEST_PASSED = 0,
+ SXEVF_DIAG_TEST_BLOCKED = 1,
+ SXEVF_DIAG_REG_PATTERN_TEST_ERR = 2,
+ SXEVF_DIAG_CHECK_REG_TEST_ERR = 3,
+};
+
+struct sxevf_hw;
+
+struct sxevf_hw_stats {
+ u64 base_vfgprc;
+ u64 base_vfgptc;
+ u64 base_vfgorc;
+ u64 base_vfgotc;
+ u64 base_vfmprc;
+
+ u64 last_vfgprc;
+ u64 last_vfgptc;
+ u64 last_vfgorc;
+ u64 last_vfgotc;
+ u64 last_vfmprc;
+
+ u64 vfgprc;
+ u64 vfgptc;
+ u64 vfgorc;
+ u64 vfgotc;
+ u64 vfmprc;
+
+ u64 saved_reset_vfgprc;
+ u64 saved_reset_vfgptc;
+ u64 saved_reset_vfgorc;
+ u64 saved_reset_vfgotc;
+ u64 saved_reset_vfmprc;
+};
+
+void sxevf_hw_ops_init(struct sxevf_hw *hw);
+
+
+struct sxevf_setup_operations {
+ void (*reset)(struct sxevf_hw *hw);
+ void (*hw_stop)(struct sxevf_hw *hw);
+ s32 (*regs_test)(struct sxevf_hw *hw);
+ u32 (*link_state_get)(struct sxevf_hw *hw);
+ u32 (*regs_dump)(struct sxevf_hw *hw, u32 *regs_buff, u32 buf_size);
+ bool (*reset_done)(struct sxevf_hw *hw);
+};
+
+struct sxevf_hw_setup {
+ const struct sxevf_setup_operations *ops;
+};
+
+struct sxevf_irq_operations {
+ void (*pending_irq_clear)(struct sxevf_hw *hw);
+ void (*ring_irq_interval_set)(struct sxevf_hw *hw, u16 irq_idx, u32 interval);
+ void (*event_irq_interval_set)(struct sxevf_hw *hw, u16 irq_idx, u32 value);
+ void (*ring_irq_map)(struct sxevf_hw *hw, bool is_tx, u16 hw_ring_idx, u16 irq_idx);
+ void (*event_irq_map)(struct sxevf_hw *hw, u16 irq_idx);
+ void (*ring_irq_trigger)(struct sxevf_hw *hw, u64 eics);
+ void (*irq_enable)(struct sxevf_hw *hw, u32 mask);
+ void (*specific_irq_enable)(struct sxevf_hw *hw, u32 value);
+ void (*irq_disable)(struct sxevf_hw *hw);
+ void (*irq_off)(struct sxevf_hw *hw);
+};
+
+struct sxevf_irq_info {
+ const struct sxevf_irq_operations *ops;
+};
+
+struct sxevf_mbx_operations {
+ u32 (*mailbox_read)(struct sxevf_hw *hw);
+ void (*mailbox_write)(struct sxevf_hw *hw, u32 value);
+
+ void (*msg_write)(struct sxevf_hw *hw, u8 index, u32 msg);
+ u32 (*msg_read)(struct sxevf_hw *hw, u8 index);
+
+ void (*pf_req_irq_trigger)(struct sxevf_hw *hw);
+ void (*pf_ack_irq_trigger)(struct sxevf_hw *hw);
+};
+
+struct sxevf_mbx_stats {
+ u32 send_msgs;
+ u32 rcv_msgs;
+
+ u32 reqs;
+ u32 acks;
+ u32 rsts;
+};
+
+struct sxevf_mbx_info {
+ const struct sxevf_mbx_operations *ops;
+
+ struct sxevf_mbx_stats stats;
+ u32 msg_len;
+ u32 retry;
+ u32 interval;
+ u32 reg_value;
+ u32 api_version;
+};
+
+struct sxevf_dma_operations {
+ void (*tx_ring_desc_configure)(struct sxevf_hw *hw, u32 desc_mem_len,
+ u64 desc_dma_addr, u8 reg_idx);
+ void (*tx_writeback_off)(struct sxevf_hw *hw, u8 reg_idx);
+ void (*tx_desc_thresh_set)(struct sxevf_hw *hw, u8 reg_idx,
+ u32 wb_thresh, u32 host_thresh, u32 prefech_thresh);
+ void (*tx_ring_switch)(struct sxevf_hw *hw, u8 reg_idx, bool is_on);
+ void (*tx_desc_wb_flush)(struct sxevf_hw *hw, u8 val);
+ void (*tx_ring_info_get)(struct sxevf_hw *hw, u8 reg_idx,
+ u32 *head, u32 *tail);
+ void (*rx_disable)(struct sxevf_hw *hw, u8 reg_idx);
+ void (*rx_ring_switch)(struct sxevf_hw *hw, u8 reg_idx, bool is_on);
+ void (*rx_ring_desc_configure)(struct sxevf_hw *hw, u32 desc_mem_len,
+ u64 desc_dma_addr, u8 reg_idx);
+ void (*rx_rcv_ctl_configure)(struct sxevf_hw *hw, u8 reg_idx,
+ u32 header_buf_len, u32 pkg_buf_len, bool drop_en);
+};
+
+struct sxevf_dma_info {
+ const struct sxevf_dma_operations *ops;
+};
+
+struct sxevf_stat_operations {
+ void (*packet_stats_get)(struct sxevf_hw *hw,
+ struct sxevf_hw_stats *stats);
+ void (*stats_init_value_get)(struct sxevf_hw *hw,
+ struct sxevf_hw_stats *stats);
+};
+
+struct sxevf_stat_info {
+ const struct sxevf_stat_operations *ops;
+};
+
+struct sxevf_dbu_operations {
+ void (*rx_max_used_ring_set)(struct sxevf_hw *hw, u16 max_rx_ring);
+
+};
+
+struct sxevf_dbu_info {
+ const struct sxevf_dbu_operations *ops;
+};
+
+enum sxevf_hw_state {
+ SXEVF_HW_STOP,
+ SXEVF_HW_FAULT,
+};
+
+struct sxevf_hw {
+ u8 __iomem *reg_base_addr;
+ void *adapter;
+
+ void *priv;
+ unsigned long state;
+ void (*fault_handle)(void *priv);
+ u32 (*reg_read)(const volatile void *reg);
+ void (*reg_write)(u32 value, volatile void *reg);
+ s32 board_type;
+
+ struct sxevf_hw_setup setup;
+ struct sxevf_irq_info irq;
+ struct sxevf_mbx_info mbx;
+
+ struct sxevf_dma_info dma;
+ struct sxevf_stat_info stat;
+ struct sxevf_dbu_info dbu;
+};
+
+struct sxevf_reg_info {
+ u32 addr;
+ u32 count;
+ u32 stride;
+ const s8 *name;
+};
+
+u16 sxevf_reg_dump_num_get(void);
+
+void sxevf_hw_fault_handle(struct sxevf_hw *hw);
+
+static inline bool sxevf_is_hw_fault(struct sxevf_hw *hw)
+{
+ return test_bit(SXEVF_HW_FAULT, &hw->state);
+}
+
+static inline void sxevf_hw_fault_handle_init(struct sxevf_hw *hw,
+ void (*handle)(void *), void *priv)
+{
+ hw->priv = priv;
+ hw->fault_handle = handle;
+}
+
+static inline void sxevf_hw_reg_handle_init(struct sxevf_hw *hw,
+ u32 (*read)(const volatile void *),
+ void (*write)(u32, volatile void *))
+{
+ hw->reg_read = read;
+ hw->reg_write = write;
+}
+
+#ifdef SXE_DPDK
+
+void sxevf_irq_disable(struct sxevf_hw *hw);
+
+void sxevf_hw_stop(struct sxevf_hw *hw);
+
+void sxevf_hw_reset(struct sxevf_hw *hw);
+
+void sxevf_msg_write(struct sxevf_hw *hw, u8 index, u32 msg);
+
+u32 sxevf_msg_read(struct sxevf_hw *hw, u8 index);
+
+u32 sxevf_mailbox_read(struct sxevf_hw *hw);
+
+void sxevf_mailbox_write(struct sxevf_hw *hw, u32 value);
+
+void sxevf_pf_req_irq_trigger(struct sxevf_hw *hw);
+
+void sxevf_pf_ack_irq_trigger(struct sxevf_hw *hw);
+
+void sxevf_rxtx_reg_init(struct sxevf_hw *hw);
+
+void sxevf_irq_enable(struct sxevf_hw *hw, u32 mask);
+
+u32 sxevf_irq_cause_get(struct sxevf_hw *hw);
+
+void sxevf_event_irq_map(struct sxevf_hw *hw, u16 vector);
+
+void sxevf_hw_ring_irq_map(struct sxevf_hw *hw, bool is_tx, u16 hw_ring_idx, u16 vector);
+
+void sxevf_ring_irq_interval_set(struct sxevf_hw *hw, u16 irq_idx, u32 interval);
+
+void sxevf_tx_desc_configure(struct sxevf_hw *hw, u32 desc_mem_len,
+ u64 desc_dma_addr, u8 reg_idx);
+
+void sxevf_rx_ring_desc_configure(struct sxevf_hw *hw, u32 desc_mem_len,
+ u64 desc_dma_addr, u8 reg_idx);
+
+void sxevf_rx_rcv_ctl_configure(struct sxevf_hw *hw, u8 reg_idx,
+ u32 header_buf_len, u32 pkg_buf_len,
+ bool drop_en);
+
+void sxevf_rss_bit_num_set(struct sxevf_hw *hw, u32 value);
+
+void sxevf_hw_vlan_tag_strip_switch(struct sxevf_hw *hw,
+ u16 reg_index, bool is_enable);
+
+void sxevf_tx_queue_thresh_set(struct sxevf_hw *hw, u8 reg_idx,
+ u32 prefech_thresh, u32 host_thresh, u32 wb_thresh);
+
+void sxevf_tx_ring_switch(struct sxevf_hw *hw, u8 reg_idx, bool is_on);
+
+void sxevf_rx_ring_switch(struct sxevf_hw *hw, u8 reg_idx, bool is_on);
+
+void sxevf_rx_desc_tail_set(struct sxevf_hw *hw, u8 reg_idx, u32 value);
+
+void sxevf_specific_irq_enable(struct sxevf_hw *hw, u32 value);
+
+void sxevf_packet_stats_get(struct sxevf_hw *hw,
+ struct sxevf_hw_stats *stats);
+
+void sxevf_stats_init_value_get(struct sxevf_hw *hw,
+ struct sxevf_hw_stats *stats);
+
+u32 sxevf_hw_rss_redir_tbl_get(struct sxevf_hw *hw, u16 reg_idx);
+
+void sxevf_hw_rss_redir_tbl_set(struct sxevf_hw *hw,
+ u16 reg_idx, u32 value);
+
+u32 sxevf_hw_rss_key_get(struct sxevf_hw *hw, u8 reg_idx);
+
+u32 sxevf_hw_rss_field_get(struct sxevf_hw *hw);
+
+void sxevf_hw_rss_field_set(struct sxevf_hw *hw, u32 rss_field);
+
+void sxevf_hw_rss_cap_switch(struct sxevf_hw *hw, bool is_on);
+
+void sxevf_hw_rss_key_set_all(struct sxevf_hw *hw, u32 *rss_key);
+
+bool sxevf_hw_is_rss_enabled(struct sxevf_hw *hw);
+
+u32 sxevf_link_state_get(struct sxevf_hw *hw);
+
+u32 sxevf_hw_regs_group_read(struct sxevf_hw *hw,
+ const struct sxevf_reg_info *regs,
+ u32 *reg_buf);
+
+#endif
+#endif
diff --git a/drivers/net/sxe/base/sxevf_regs.h b/drivers/net/sxe/base/sxevf_regs.h
new file mode 100644
index 0000000000..50a22f559c
--- /dev/null
+++ b/drivers/net/sxe/base/sxevf_regs.h
@@ -0,0 +1,119 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#ifndef __SXEVF_REGS_H__
+#define __SXEVF_REGS_H__
+
+#define SXEVF_REG_READ_FAIL 0xffffffffU
+#define SXEVF_REG_READ_RETRY 5
+
+#define SXE_VFLINKS_UP 0x00000008
+#define SXE_VFLINKS_SPEED 0x00000006
+#define SXE_VFLINKS_SPEED_10G 0x00000006
+#define SXE_VFLINKS_SPEED_1G 0x00000004
+#define SXE_VFLINKS_SPEED_100 0x00000002
+
+#define SXE_VFCTRL 0x00000
+#define SXE_VFSTATUS 0x00008
+#define SXE_VFLINKS 0x00018
+#define SXE_VFFRTIMER 0x00048
+#define SXE_VFRXMEMWRAP 0x03190
+#define SXE_VFEICR 0x00100
+#define SXE_VFEICS 0x00104
+#define SXE_VFEIMS 0x00108
+#define SXE_VFEIMC 0x0010C
+#define SXE_VFEIAM 0x00114
+#define SXE_VFEITR(x) (0x00820 + (4 * (x)))
+#define SXE_VFIVAR(x) (0x00120 + (4 * (x)))
+#define SXE_VFIVAR_MISC 0x00140
+#define SXE_VFRDBAL(x) (0x01000 + (0x40 * (x)))
+#define SXE_VFRDBAH(x) (0x01004 + (0x40 * (x)))
+#define SXE_VFRDLEN(x) (0x01008 + (0x40 * (x)))
+#define SXE_VFRDH(x) (0x01010 + (0x40 * (x)))
+#define SXE_VFRDT(x) (0x01018 + (0x40 * (x)))
+#define SXE_VFRXDCTL(x) (0x01028 + (0x40 * (x)))
+#define SXE_VFSRRCTL(x) (0x01014 + (0x40 * (x)))
+#define SXE_VFLROCTL(x) (0x0102C + (0x40 * (x)))
+#define SXE_VFPSRTYPE 0x00300
+#define SXE_VFTDBAL(x) (0x02000 + (0x40 * (x)))
+#define SXE_VFTDBAH(x) (0x02004 + (0x40 * (x)))
+#define SXE_VFTDLEN(x) (0x02008 + (0x40 * (x)))
+#define SXE_VFTDH(x) (0x02010 + (0x40 * (x)))
+#define SXE_VFTDT(x) (0x02018 + (0x40 * (x)))
+#define SXE_VFTXDCTL(x) (0x02028 + (0x40 * (x)))
+#define SXE_VFTDWBAL(x) (0x02038 + (0x40 * (x)))
+#define SXE_VFTDWBAH(x) (0x0203C + (0x40 * (x)))
+#define SXE_VFDCA_RXCTRL(x) (0x0100C + (0x40 * (x)))
+#define SXE_VFDCA_TXCTRL(x) (0x0200c + (0x40 * (x)))
+#define SXE_VFGPRC 0x0101C
+#define SXE_VFGPTC 0x0201C
+#define SXE_VFGORC_LSB 0x01020
+#define SXE_VFGORC_MSB 0x01024
+#define SXE_VFGOTC_LSB 0x02020
+#define SXE_VFGOTC_MSB 0x02024
+#define SXE_VFMPRC 0x01034
+#define SXE_VFMRQC 0x3000
+#define SXE_VFRSSRK(x) (0x3100 + ((x) * 4))
+#define SXE_VFRETA(x) (0x3200 + ((x) * 4))
+
+#define SXEVF_VFEIMC_IRQ_MASK (7)
+#define SXEVF_IVAR_ALLOC_VALID (0x80)
+
+#define SXEVF_EITR_CNT_WDIS (0x80000000)
+#define SXEVF_EITR_ITR_MASK (0x00000FF8)
+#define SXEVF_EITR_ITR_SHIFT (2)
+#define SXEVF_EITR_ITR_MAX (SXEVF_EITR_ITR_MASK >> SXEVF_EITR_ITR_SHIFT)
+
+#define SXE_VFRXDCTL_ENABLE 0x02000000
+#define SXE_VFTXDCTL_ENABLE 0x02000000
+#define SXE_VFCTRL_RST 0x04000000
+
+#define SXEVF_RXDCTL_ENABLE 0x02000000
+#define SXEVF_RXDCTL_VME 0x40000000
+
+#define SXEVF_PSRTYPE_RQPL_SHIFT 29
+
+#define SXEVF_SRRCTL_DROP_EN 0x10000000
+#define SXEVF_SRRCTL_DESCTYPE_DATA_ONEBUF 0x02000000
+#define SXEVF_SRRCTL_BSIZEPKT_SHIFT (10)
+#define SXEVF_SRRCTL_BSIZEHDRSIZE_SHIFT (2)
+#define SXEVF_SRRCTL_BSIZEPKT_MASK 0x0000007F
+#define SXEVF_SRRCTL_BSIZEHDR_MASK 0x00003F00
+
+#define SXE_VFMAILBOX 0x002FC
+#define SXE_VFMBMEM 0x00200
+
+#define SXE_VFMAILBOX_REQ 0x00000001
+#define SXE_VFMAILBOX_ACK 0x00000002
+#define SXE_VFMAILBOX_VFU 0x00000004
+#define SXE_VFMAILBOX_PFU 0x00000008
+#define SXE_VFMAILBOX_PFSTS 0x00000010
+#define SXE_VFMAILBOX_PFACK 0x00000020
+#define SXE_VFMAILBOX_RSTI 0x00000040
+#define SXE_VFMAILBOX_RSTD 0x00000080
+#define SXE_VFMAILBOX_RC_BIT 0x000000B0
+
+#define SXEVF_TDBAL(_i) (0x02000 + ((_i) * 0x40))
+#define SXEVF_TDBAH(_i) (0x02004 + ((_i) * 0x40))
+#define SXEVF_TDLEN(_i) (0x02008 + ((_i) * 0x40))
+#define SXEVF_TDH(_i) (0x02010 + ((_i) * 0x40))
+#define SXEVF_TDT(_i) (0x02018 + ((_i) * 0x40))
+#define SXEVF_TXDCTL(_i) (0x02028 + ((_i) * 0x40))
+#define SXEVF_TDWBAL(_i) (0x02038 + ((_i) * 0x40))
+#define SXEVF_TDWBAH(_i) (0x0203C + ((_i) * 0x40))
+
+#define SXEVF_TXDCTL_SWFLSH (0x02000000)
+#define SXEVF_TXDCTL_ENABLE (0x02000000)
+
+#define SXEVF_VFGPRC 0x0101C
+#define SXEVF_VFGPTC 0x0201C
+#define SXEVF_VFGORC_LSB 0x01020
+#define SXEVF_VFGORC_MSB 0x01024
+#define SXEVF_VFGOTC_LSB 0x02020
+#define SXEVF_VFGOTC_MSB 0x02024
+#define SXEVF_VFMPRC 0x01034
+
+#define SXEVF_EICR_MASK 0x07
+
+#endif
diff --git a/drivers/net/sxe/meson.build b/drivers/net/sxe/meson.build
index f53ca7ecaf..a3b874b7e2 100644
--- a/drivers/net/sxe/meson.build
+++ b/drivers/net/sxe/meson.build
@@ -11,26 +11,38 @@ cflags += ['-DSXE_DPDK_SIMD']
deps += ['hash']
sources = files(
- 'pf/sxe_main.c',
+ 'pf/sxe_main.c',
'pf/sxe_filter.c',
- 'pf/sxe_flow_ctrl.c',
- 'pf/sxe_irq.c',
- 'pf/sxe_ethdev.c',
+ 'pf/sxe_flow_ctrl.c',
+ 'pf/sxe_irq.c',
+ 'pf/sxe_ethdev.c',
'pf/sxe_offload.c',
'pf/sxe_queue.c',
'pf/sxe_rx.c',
'pf/sxe_tx.c',
'pf/sxe_stats.c',
- 'pf/sxe_pmd_hdc.c',
- 'pf/sxe_phy.c',
- 'pf/sxe_ptp.c',
- 'pf/sxe_dcb.c',
- 'base/sxe_queue_common.c',
+ 'pf/sxe_pmd_hdc.c',
+ 'pf/sxe_phy.c',
+ 'pf/sxe_ptp.c',
+ 'pf/sxe_vf.c',
+ 'pf/sxe_dcb.c',
+ 'vf/sxevf_main.c',
+ 'vf/sxevf_filter.c',
+ 'vf/sxevf_irq.c',
+ 'vf/sxevf_msg.c',
+ 'vf/sxevf_ethdev.c',
+ 'vf/sxevf_stats.c',
+ 'vf/sxevf_rx.c',
+ 'vf/sxevf_tx.c',
+ 'vf/sxevf_queue.c',
+ 'vf/sxevf_offload.c',
+ 'base/sxe_queue_common.c',
'base/sxe_rx_common.c',
'base/sxe_tx_common.c',
'base/sxe_offload_common.c',
- 'base/sxe_common.c',
- 'base/sxe_hw.c',
+ 'base/sxe_common.c',
+ 'base/sxe_hw.c',
+ 'base/sxevf_hw.c',
)
testpmd_sources = files('sxe_testpmd.c')
@@ -43,5 +55,6 @@ endif
includes += include_directories('base')
includes += include_directories('pf')
+includes += include_directories('vf')
includes += include_directories('include/sxe/')
-includes += include_directories('include/')
+includes += include_directories('include/')
\ No newline at end of file
diff --git a/drivers/net/sxe/pf/rte_pmd_sxe.h b/drivers/net/sxe/pf/rte_pmd_sxe.h
index 16406c6c26..69b0df2bd1 100644
--- a/drivers/net/sxe/pf/rte_pmd_sxe.h
+++ b/drivers/net/sxe/pf/rte_pmd_sxe.h
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (C), 2022, Linkdata Technology Co., Ltd.
*/
-
#ifndef __PMD_SXE_H__
#define __PMD_SXE_H__
@@ -13,4 +12,7 @@ typedef int32_t s32;
s32 rte_pmd_sxe_tx_loopback_set(u16 port, u8 on);
s32 rte_pmd_sxe_tc_bw_set(u8 port, u8 tc_num, u8 *bw_weight);
+
+int rte_pmd_sxe_set_vf_rxmode(u16 port, u16 vf,
+u16 rx_mask, u8 on);
#endif
diff --git a/drivers/net/sxe/pf/sxe.h b/drivers/net/sxe/pf/sxe.h
index 1b24a9b9e7..212929cf04 100644
--- a/drivers/net/sxe/pf/sxe.h
+++ b/drivers/net/sxe/pf/sxe.h
@@ -11,8 +11,9 @@
#include "sxe_types.h"
#include "sxe_stats.h"
#include "sxe_irq.h"
-#include "sxe_phy.h"
+#include "sxe_vf.h"
#include "sxe_dcb.h"
+#include "sxe_phy.h"
#include "sxe_hw.h"
struct sxe_hw;
@@ -60,6 +61,8 @@ struct sxe_adapter {
#endif
struct sxe_ptp_context ptp_ctxt;
struct sxe_phy_context phy_ctxt;
+ struct sxe_virtual_context vt_ctxt;
+
struct sxe_stats_info stats_info;
struct sxe_dcb_context dcb_ctxt;
diff --git a/drivers/net/sxe/pf/sxe_filter.c b/drivers/net/sxe/pf/sxe_filter.c
index fd3a3c0984..55c534d692 100644
--- a/drivers/net/sxe/pf/sxe_filter.c
+++ b/drivers/net/sxe/pf/sxe_filter.c
@@ -10,7 +10,9 @@
#include "sxe_logs.h"
#include "sxe.h"
#include "sxe_queue.h"
+#include "drv_msg.h"
#include "sxe_pmd_hdc.h"
+#include "sxe_cli.h"
#include "sxe_compat_version.h"
#define PF_POOL_INDEX(p) (p)
@@ -124,6 +126,45 @@ static u8 sxe_sw_uc_entry_del(struct sxe_adapter *adapter, u8 index)
return i;
}
+u8 sxe_sw_uc_entry_vf_add(struct sxe_adapter *adapter,
+ u8 vf_idx, u8 *mac_addr, bool macvlan)
+{
+ u8 i;
+ struct sxe_uc_addr_table *uc_table = adapter->mac_filter_ctxt.uc_addr_table;
+
+ for (i = 0; i < SXE_UC_ENTRY_NUM_MAX; i++) {
+ if (!uc_table[i].used) {
+ uc_table[i].used = true;
+ uc_table[i].rar_idx = i;
+ uc_table[i].pool_idx = vf_idx;
+ uc_table[i].type = macvlan ? SXE_VF_MACVLAN : SXE_VF;
+ rte_memcpy(uc_table[i].addr, mac_addr, SXE_MAC_ADDR_LEN);
+ break;
+ }
+ }
+
+ return i;
+}
+
+void sxe_sw_uc_entry_vf_del(struct sxe_adapter *adapter, u8 vf_idx,
+ bool macvlan)
+{
+ u8 i;
+ struct sxe_uc_addr_table *uc_table = adapter->mac_filter_ctxt.uc_addr_table;
+
+ for (i = 0; i < SXE_UC_ENTRY_NUM_MAX; i++) {
+ if (!uc_table[i].used || uc_table[i].type == SXE_PF)
+ continue;
+
+ if (uc_table[i].pool_idx == vf_idx) {
+ uc_table[i].used = false;
+ sxe_hw_uc_addr_del(&adapter->hw, i);
+ if (!macvlan)
+ break;
+ }
+ }
+}
+
s32 sxe_mac_addr_init(struct rte_eth_dev *eth_dev)
{
struct sxe_adapter *adapter = eth_dev->data->dev_private;
@@ -341,6 +382,40 @@ s32 sxe_allmulticast_disable(struct rte_eth_dev *dev)
return 0;
}
+static void sxe_vf_promisc_mac_update_all(struct rte_eth_dev *dev)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_vf_info *vf_info = adapter->vt_ctxt.vf_info;
+ struct sxe_uc_addr_table *uc_table = adapter->mac_filter_ctxt.uc_addr_table;
+ u16 vf_num = sxe_vf_num_get(dev);
+ u8 vf_idx = 0;
+ s32 i;
+
+ for (vf_idx = 0; vf_idx < vf_num; vf_idx++) {
+ if (vf_info[vf_idx].cast_mode == SXE_CAST_MODE_PROMISC) {
+ for (i = 0; i < SXE_UC_ENTRY_NUM_MAX; i++) {
+ if (uc_table[i].used) {
+ sxe_hw_uc_addr_pool_enable(&adapter->hw,
+ uc_table[i].rar_idx, vf_idx);
+ }
+ }
+ }
+ }
+}
+
+static void sxe_vf_promisc_mac_update(struct rte_eth_dev *dev, u32 rar_idx)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_vf_info *vf_info = adapter->vt_ctxt.vf_info;
+ u16 vf_num = sxe_vf_num_get(dev);
+ u8 vf_idx;
+
+ for (vf_idx = 0; vf_idx < vf_num; vf_idx++) {
+ if (vf_info[vf_idx].cast_mode == SXE_CAST_MODE_PROMISC)
+ sxe_hw_uc_addr_pool_enable(&adapter->hw, rar_idx, vf_idx);
+ }
+}
+
s32 sxe_mac_addr_add(struct rte_eth_dev *dev,
struct rte_ether_addr *mac_addr,
u32 index, u32 pool)
@@ -469,6 +544,108 @@ static void sxe_hash_mac_addr_parse(u8 *mac_addr, u16 *reg_idx,
mac_addr[4], mac_addr[5], *reg_idx, *bit_idx);
}
+s32 sxe_uc_hash_table_set(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mac_addr, u8 on)
+{
+ u16 bit_idx;
+ u16 reg_idx;
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_mac_filter_context *mac_filter = &adapter->mac_filter_ctxt;
+ u32 value;
+ s32 ret = 0;
+ u8 *addr;
+
+ sxe_hash_mac_addr_parse(mac_addr->addr_bytes, ®_idx, &bit_idx);
+
+ value = (mac_filter->uta_hash_table[reg_idx] >> bit_idx) & 0x1;
+ if (value == on)
+ goto l_out;
+
+ value = sxe_hw_uta_hash_table_get(hw, reg_idx);
+ if (on) {
+ mac_filter->uta_used_count++;
+ value |= (0x1 << bit_idx);
+ mac_filter->uta_hash_table[reg_idx] |= (0x1 << bit_idx);
+ } else {
+ mac_filter->uta_used_count--;
+ value &= ~(0x1 << bit_idx);
+ mac_filter->uta_hash_table[reg_idx] &= ~(0x1 << bit_idx);
+ }
+
+ sxe_hw_uta_hash_table_set(hw, reg_idx, value);
+
+ addr = mac_addr->addr_bytes;
+ PMD_LOG_INFO(DRV, "mac_addr:" RTE_ETHER_ADDR_PRT_FMT " uta reg_idx:%u bit_idx:%u"
+ " %s done, uta_used_count:%u",
+ addr[0], addr[1], addr[2],
+ addr[3], addr[4], addr[5],
+ reg_idx, bit_idx,
+ on ? "set" : "clear",
+ mac_filter->uta_used_count);
+
+l_out:
+ return ret;
+}
+
+s32 sxe_uc_all_hash_table_set(struct rte_eth_dev *dev, u8 on)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_mac_filter_context *mac_filter = &adapter->mac_filter_ctxt;
+ u32 value;
+ u8 i;
+
+ value = on ? (~0) : 0;
+
+ for (i = 0; i < SXE_UTA_ENTRY_NUM_MAX; i++) {
+ mac_filter->uta_hash_table[i] = value;
+ sxe_hw_uta_hash_table_set(hw, i, value);
+ }
+
+ PMD_LOG_INFO(DRV, "uta table all entry %s done.",
+ on ? "set" : "clear");
+
+ return 0;
+}
+
+s32 sxe_set_mc_addr_list(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mc_addr_list,
+ u32 nb_mc_addr)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_mac_filter_context *mac_filter = &adapter->mac_filter_ctxt;
+ u16 vf_num = sxe_vf_num_get(dev);
+ u32 vm_l2_ctrl = sxe_hw_pool_rx_mode_get(hw, vf_num);
+ u32 i;
+ u16 bit_idx;
+ u16 reg_idx;
+
+ memset(&mac_filter->mta_hash_table, 0, sizeof(mac_filter->mta_hash_table));
+ for (i = 0; i < nb_mc_addr; i++) {
+ sxe_hash_mac_addr_parse(mc_addr_list->addr_bytes, ®_idx, &bit_idx);
+ mc_addr_list++;
+ mac_filter->mta_hash_table[reg_idx] |= (0x1 << bit_idx);
+ }
+
+ for (i = 0; i < SXE_MTA_ENTRY_NUM_MAX; i++)
+ sxe_hw_mta_hash_table_set(hw, i, mac_filter->mta_hash_table[i]);
+
+ if (nb_mc_addr) {
+ sxe_hw_mc_filter_enable(hw);
+
+ if (vf_num > 0) {
+ vm_l2_ctrl |= SXE_VMOLR_ROMPE;
+ sxe_hw_pool_rx_mode_set(hw, vm_l2_ctrl, vf_num);
+ }
+ }
+
+ PMD_LOG_INFO(DRV, "mc addr list cnt:%u set to mta done.", nb_mc_addr);
+
+ return 0;
+}
+
s32 sxe_vlan_filter_set(struct rte_eth_dev *eth_dev, u16 vlan_id, s32 on)
{
struct sxe_adapter *adapter = eth_dev->data->dev_private;
diff --git a/drivers/net/sxe/pf/sxe_filter.h b/drivers/net/sxe/pf/sxe_filter.h
index da40c75d84..de6170a3f4 100644
--- a/drivers/net/sxe/pf/sxe_filter.h
+++ b/drivers/net/sxe/pf/sxe_filter.h
@@ -73,6 +73,15 @@ void sxe_mac_addr_remove(struct rte_eth_dev *dev, u32 rar_idx);
s32 sxe_mac_addr_set(struct rte_eth_dev *dev,
struct rte_ether_addr *mac_addr);
+s32 sxe_uc_hash_table_set(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mac_addr, u8 on);
+
+s32 sxe_uc_all_hash_table_set(struct rte_eth_dev *dev, u8 on);
+
+s32 sxe_set_mc_addr_list(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mc_addr_list,
+ u32 nb_mc_addr);
+
s32 sxe_vlan_filter_set(struct rte_eth_dev *eth_dev, u16 vlan_id, s32 on);
s32 sxe_vlan_tpid_set(struct rte_eth_dev *eth_dev,
@@ -92,4 +101,10 @@ void sxe_vlan_strip_switch_set(struct rte_eth_dev *dev);
void sxe_fc_mac_addr_set(struct sxe_adapter *adapter);
+u8 sxe_sw_uc_entry_vf_add(struct sxe_adapter *adapter,
+ u8 vf_idx, u8 *mac_addr, bool macvlan);
+
+void sxe_sw_uc_entry_vf_del(struct sxe_adapter *adapter, u8 vf_idx,
+ bool macvlan);
+
#endif
diff --git a/drivers/net/sxe/pf/sxe_main.c b/drivers/net/sxe/pf/sxe_main.c
index 85bd87d495..49f9dd2f27 100644
--- a/drivers/net/sxe/pf/sxe_main.c
+++ b/drivers/net/sxe/pf/sxe_main.c
@@ -20,10 +20,12 @@
#include "sxe_ethdev.h"
#include "sxe.h"
#include "drv_msg.h"
+#include "sxe_cli.h"
#include "sxe_queue.h"
#include "sxe_errno.h"
#include "sxe_compat_platform.h"
#include "sxe_pmd_hdc.h"
+#include "sxe_vf.h"
#include "sxe_queue.h"
static const struct rte_pci_id sxe_pci_tbl[] = {
diff --git a/drivers/net/sxe/pf/sxe_phy.h b/drivers/net/sxe/pf/sxe_phy.h
index 9fd2746ec8..d907b3c8f8 100644
--- a/drivers/net/sxe/pf/sxe_phy.h
+++ b/drivers/net/sxe/pf/sxe_phy.h
@@ -6,6 +6,7 @@
#include <rte_ethdev.h>
#include "drv_msg.h"
+#include "sxe_cli.h"
#include "sxe_msg.h"
#define SXE_SFF_BASE_ADDR 0x0
diff --git a/drivers/net/sxe/pf/sxe_stats.c b/drivers/net/sxe/pf/sxe_stats.c
index 6b9e1beb3e..af3c0bf84c 100644
--- a/drivers/net/sxe/pf/sxe_stats.c
+++ b/drivers/net/sxe/pf/sxe_stats.c
@@ -219,10 +219,9 @@ s32 sxe_xstats_get(struct rte_eth_dev *eth_dev,
u8 prio;
cnt = SXE_XSTAT_CNT;
- PMD_LOG_INFO(DRV, "xstat size:%u. hw xstat field cnt:%u "
- "fc xstat field cnt:%u ", cnt,
- SXE_XSTAT_MAC_CNT,
- SXE_XSTAT_FC_CNT);
+ PMD_LOG_INFO(DRV, "xstat size:%u. hw xstat field cnt: %" SXE_PRIU64
+ "fc xstat field cnt: %" SXE_PRIU64, cnt,
+ SXE_XSTAT_MAC_CNT, SXE_XSTAT_FC_CNT);
if (usr_cnt < cnt) {
ret = cnt;
@@ -333,7 +332,7 @@ s32 sxe_xstats_names_get(__rte_unused struct rte_eth_dev *dev,
if (usr_cnt < SXE_XSTAT_CNT) {
ret = -SXE_ERR_PARAM;
- PMD_LOG_ERR(DRV, "max:%u usr_cnt:%u invalid.(err:%d)",
+ PMD_LOG_ERR(DRV, "max: %" SXE_PRIU64 " usr_cnt:%u invalid.(err:%d)",
SXE_XSTAT_CNT, usr_cnt, ret);
goto l_out;
}
diff --git a/drivers/net/sxe/pf/sxe_vf.c b/drivers/net/sxe/pf/sxe_vf.c
new file mode 100644
index 0000000000..d75ec913f3
--- /dev/null
+++ b/drivers/net/sxe/pf/sxe_vf.c
@@ -0,0 +1,1427 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+#if defined SXE_DPDK_L4_FEATURES && defined SXE_DPDK_SRIOV
+
+#include <rte_ethdev.h>
+#include <rte_ether.h>
+#include <rte_memcpy.h>
+#include "sxe_dpdk_version.h"
+#include <ethdev_driver.h>
+#include <ethdev_pci.h>
+#include <bus_pci_driver.h>
+
+#include "sxe_logs.h"
+#include "sxe_vf.h"
+#include "sxe_hw.h"
+#include "sxe.h"
+#include "sxe_errno.h"
+#include "sxe_filter.h"
+#include "sxe_offload.h"
+#include "sxe_ethdev.h"
+#include "sxe_rx.h"
+#include "rte_pmd_sxe.h"
+
+#define SXE_MR_VLAN_MASK 0xFFFFFFFF
+#define SXE_MR_VLAN_MSB_BIT_OFFSET 32
+
+#define SXE_MR_VIRTUAL_POOL_MASK 0xFFFFFFFF
+#define SXE_MR_VIRTUAL_POOL_MSB_BIT_MASK 32
+
+#define SXE_UC_MAC_UNSET 0
+#define SXE_UC_MAC_SET 1
+
+static inline s32 sxe_vf_mac_addr_generate(struct rte_eth_dev *eth_dev, u16 vf_num)
+{
+ u8 vf_mac_addr[RTE_ETHER_ADDR_LEN];
+ struct sxe_adapter *adapter = eth_dev->data->dev_private;
+ struct sxe_vf_info *vf_info = adapter->vt_ctxt.vf_info;
+ u16 idx;
+
+ for (idx = 0; idx < vf_num; idx++) {
+ rte_eth_random_addr(vf_mac_addr);
+ memcpy(vf_info[idx].mac_addr, vf_mac_addr, RTE_ETHER_ADDR_LEN);
+ }
+
+ return 0;
+}
+
+static void sxe_vt_mode_configure(struct rte_eth_dev *eth_dev)
+{
+ struct sxe_adapter *adapter = eth_dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ u32 gpie;
+ u32 pcie_ext;
+
+ pcie_ext = sxe_hw_pcie_vt_mode_get(hw);
+ pcie_ext &= ~SXE_GCR_EXT_VT_MODE_MASK;
+
+ gpie = sxe_hw_irq_general_reg_get(hw);
+ gpie &= ~SXE_GPIE_VTMODE_MASK;
+ gpie |= SXE_GPIE_MSIX_MODE;
+
+ switch (RTE_ETH_DEV_SRIOV(eth_dev).active) {
+ case RTE_ETH_64_POOLS:
+ pcie_ext |= SXE_GCR_EXT_VT_MODE_64;
+ gpie |= SXE_GPIE_VTMODE_64;
+ break;
+ case RTE_ETH_32_POOLS:
+ pcie_ext |= SXE_GCR_EXT_VT_MODE_32;
+ gpie |= SXE_GPIE_VTMODE_32;
+ break;
+ case RTE_ETH_16_POOLS:
+ pcie_ext |= SXE_GCR_EXT_VT_MODE_16;
+ gpie |= SXE_GPIE_VTMODE_16;
+ break;
+ }
+
+ sxe_hw_pcie_vt_mode_set(hw, pcie_ext);
+ sxe_hw_irq_general_reg_set(hw, gpie);
+}
+
+s32 sxe_vt_init(struct rte_eth_dev *eth_dev)
+{
+ struct sxe_adapter *adapter = eth_dev->data->dev_private;
+ struct sxe_vf_info **vf_info = &adapter->vt_ctxt.vf_info;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_irq_context *irq = &adapter->irq_ctxt;
+ u16 vf_num;
+ s32 ret = 0;
+ u8 nb_queue;
+
+ PMD_INIT_FUNC_TRACE();
+
+ RTE_ETH_DEV_SRIOV(eth_dev).active = 0;
+ /* get vf num from max_vfs or sriov_numvfs */
+ vf_num = sxe_vf_num_get(eth_dev);
+ if (vf_num == 0) {
+ LOG_WARN_BDF("no vf, no need init vt");
+ goto l_out;
+ }
+
+ *vf_info = rte_zmalloc("vf_info", sizeof(struct sxe_vf_info) * vf_num, 0);
+ if (*vf_info == NULL) {
+ LOG_WARN_BDF("vf_info allocate memory fail.");
+ ret = -ENOMEM;
+ goto l_out;
+ }
+
+ ret = rte_eth_switch_domain_alloc(&(*vf_info)->domain_id);
+ if (ret) {
+ LOG_ERROR_BDF("failed to allocate switch domain for device %d", ret);
+ goto l_free_vf_info;
+ }
+
+ if (vf_num >= RTE_ETH_32_POOLS) {
+ nb_queue = 2;
+ RTE_ETH_DEV_SRIOV(eth_dev).active = RTE_ETH_64_POOLS;
+ } else if (vf_num >= RTE_ETH_16_POOLS) {
+ nb_queue = 4;
+ RTE_ETH_DEV_SRIOV(eth_dev).active = RTE_ETH_32_POOLS;
+ } else {
+ nb_queue = 8;
+ RTE_ETH_DEV_SRIOV(eth_dev).active = RTE_ETH_16_POOLS;
+ }
+
+ RTE_ETH_DEV_SRIOV(eth_dev).nb_q_per_pool = nb_queue;
+ RTE_ETH_DEV_SRIOV(eth_dev).def_vmdq_idx = vf_num;
+ RTE_ETH_DEV_SRIOV(eth_dev).def_pool_q_idx = (u16)(vf_num * nb_queue);
+
+ sxe_vf_mac_addr_generate(eth_dev, vf_num);
+
+ sxe_hw_mbx_init(hw);
+
+ irq->enable_mask |= SXE_EIMS_MAILBOX;
+
+ adapter->vt_ctxt.promisc_cnt = 0;
+
+ sxe_vt_mode_configure(eth_dev);
+
+ LOG_INFO_BDF("vf_num:%d domain id:%u init done.",
+ vf_num, (*vf_info)->domain_id);
+
+l_out:
+ return ret;
+
+l_free_vf_info:
+ rte_free(*vf_info);
+ *vf_info = NULL;
+ return ret;
+}
+
+static void sxe_pf_pool_enable(struct rte_eth_dev *eth_dev, u16 vf_num)
+{
+ struct sxe_adapter *adapter = eth_dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ u32 enable_mask = ~0;
+ u8 vf_reg_idx = ((vf_num >> 5) > 0) ? 1 : 0;
+ u8 vf_bit_index = vf_num & ((1 << 5) - 1);
+
+ sxe_hw_rx_pool_bitmap_set(hw, vf_reg_idx, enable_mask << vf_bit_index);
+ sxe_hw_rx_pool_bitmap_set(hw, (vf_reg_idx ^ 1), (vf_reg_idx - 1));
+
+ sxe_hw_tx_pool_bitmap_set(hw, vf_reg_idx, enable_mask << vf_bit_index);
+ sxe_hw_tx_pool_bitmap_set(hw, (vf_reg_idx ^ 1), (vf_reg_idx - 1));
+}
+
+static void sxe_vf_vlan_filter_enable(struct rte_eth_dev *eth_dev)
+{
+ struct sxe_adapter *adapter = eth_dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ u32 enable_mask = ~0;
+ u32 vlan_ctl;
+ u8 i;
+
+ vlan_ctl = sxe_hw_vlan_type_get(hw);
+ vlan_ctl |= SXE_VLNCTRL_VFE;
+ sxe_hw_vlan_type_set(hw, vlan_ctl);
+
+ for (i = 0; i < SXE_VFT_TBL_SIZE; i++)
+ sxe_hw_vlan_filter_array_write(hw, i, enable_mask);
+}
+
+static void sxe_uc_mac_table_init(struct rte_eth_dev *eth_dev)
+{
+ struct sxe_adapter *adapter = eth_dev->data->dev_private;
+ struct sxe_vf_info *vf_info = adapter->vt_ctxt.vf_info;
+ u8 vf_num = sxe_vf_num_get(eth_dev);
+ u8 i;
+
+ for (i = 0; i < vf_num; i++)
+ memset(vf_info[i].uc_mac_table, SXE_UC_MAC_UNSET, SXE_UC_ENTRY_NUM_MAX);
+}
+
+void sxe_vt_configure(struct rte_eth_dev *eth_dev)
+{
+ struct sxe_adapter *adapter = eth_dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ u16 vf_num;
+ u16 pf_pool_idx = RTE_ETH_DEV_SRIOV(eth_dev).def_vmdq_idx;
+
+ vf_num = sxe_vf_num_get(eth_dev);
+ if (vf_num == 0) {
+ LOG_WARN_BDF("no vf, no need configure vt");
+ return;
+ }
+
+ sxe_hw_vt_ctrl_cfg(hw, pf_pool_idx);
+
+ sxe_pf_pool_enable(eth_dev, vf_num);
+
+ sxe_hw_vt_pool_loopback_switch(hw, true);
+
+ sxe_hw_mac_pool_clear(hw, 0);
+ sxe_hw_mac_pool_clear(hw, SXE_UC_ENTRY_NUM_MAX - 1);
+
+ sxe_hw_uc_addr_pool_enable(hw, 0, pf_pool_idx);
+
+ sxe_vt_mode_configure(eth_dev);
+
+ sxe_vf_vlan_filter_enable(eth_dev);
+
+ sxe_hw_pool_mac_anti_spoof_set(hw, vf_num, 0);
+
+ sxe_uc_mac_table_init(eth_dev);
+
+ sxe_rx_fc_threshold_set(hw);
+}
+
+void sxe_vt_uninit(struct rte_eth_dev *eth_dev)
+{
+ struct sxe_adapter *adapter = eth_dev->data->dev_private;
+ struct sxe_vf_info **vf_info = &adapter->vt_ctxt.vf_info;
+ u16 vf_num;
+ int ret;
+
+ PMD_INIT_FUNC_TRACE();
+
+ RTE_ETH_DEV_SRIOV(eth_dev).active = 0;
+ RTE_ETH_DEV_SRIOV(eth_dev).nb_q_per_pool = 0;
+ RTE_ETH_DEV_SRIOV(eth_dev).def_vmdq_idx = 0;
+ RTE_ETH_DEV_SRIOV(eth_dev).def_pool_q_idx = 0;
+
+ vf_num = sxe_vf_num_get(eth_dev);
+ if (vf_num == 0 || (*vf_info) == NULL) {
+ LOG_INFO_BDF("vf_num:%u vf_info:%p, no need free vf_info.",
+ vf_num, *vf_info);
+ return;
+ }
+
+ ret = rte_eth_switch_domain_free((*vf_info)->domain_id);
+ if (ret)
+ LOG_ERROR_BDF("failed to free switch domain: %d", ret);
+
+ rte_free(*vf_info);
+ *vf_info = NULL;
+}
+
+s32 sxe_vf_rss_configure(struct rte_eth_dev *dev)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ bool is_4q_per_pool;
+ s32 ret = 0;
+
+ sxe_rss_configure(dev);
+
+ switch (RTE_ETH_DEV_SRIOV(dev).active) {
+ case RTE_ETH_64_POOLS:
+ is_4q_per_pool = false;
+ break;
+
+ case RTE_ETH_32_POOLS:
+ is_4q_per_pool = true;
+ break;
+
+ default:
+ ret = -EINVAL;
+ LOG_ERROR_BDF("invalid pool number:%u in iov mode with rss.(err:%d)",
+ RTE_ETH_DEV_SRIOV(dev).active, ret);
+ goto l_out;
+ }
+
+ sxe_hw_rx_multi_ring_configure(hw, 0, is_4q_per_pool, true);
+
+ LOG_INFO_BDF("pool num:%u is_4q_per_pool:%u configure done.",
+ RTE_ETH_DEV_SRIOV(dev).active, is_4q_per_pool);
+
+l_out:
+ return ret;
+}
+
+s32 sxe_vf_default_mode_configure(struct rte_eth_dev *dev)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ s32 ret = 0;
+ u8 tcs = 0;
+ bool is_4q_per_pool = false;
+
+ switch (RTE_ETH_DEV_SRIOV(dev).active) {
+ case RTE_ETH_64_POOLS:
+ is_4q_per_pool = false;
+ break;
+
+ case RTE_ETH_32_POOLS:
+ is_4q_per_pool = true;
+ break;
+
+ case RTE_ETH_16_POOLS:
+ tcs = 8;
+ break;
+ default:
+ ret = -SXE_ERR_CONFIG;
+ LOG_ERROR_BDF("invalid pool number:%u (err:%d)",
+ RTE_ETH_DEV_SRIOV(dev).active, ret);
+ goto l_out;
+ }
+
+ sxe_hw_rx_multi_ring_configure(hw, tcs, is_4q_per_pool, true);
+
+l_out:
+ return ret;
+}
+
+static void sxe_filter_mode_configure(struct rte_eth_dev *dev)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ u16 vf_num = sxe_vf_num_get(dev);
+ u32 filter_ctrl = sxe_hw_rx_mode_get(hw);
+ u32 vm_l2_ctrl = SXE_VMOLR_AUPE | SXE_VMOLR_BAM;
+
+ filter_ctrl &= ~(SXE_FCTRL_SBP | SXE_FCTRL_UPE | SXE_FCTRL_MPE);
+
+ filter_ctrl |= SXE_FCTRL_BAM;
+
+ if (dev->data->promiscuous) {
+ filter_ctrl |= (SXE_FCTRL_UPE | SXE_FCTRL_MPE);
+ vm_l2_ctrl |= (SXE_VMOLR_ROPE | SXE_VMOLR_MPE);
+ } else {
+ if (dev->data->all_multicast) {
+ filter_ctrl |= SXE_FCTRL_MPE;
+ vm_l2_ctrl |= SXE_VMOLR_MPE;
+ } else {
+ vm_l2_ctrl |= SXE_VMOLR_ROMPE;
+ }
+ }
+
+ vm_l2_ctrl |= sxe_hw_pool_rx_mode_get(hw, vf_num) &
+ ~(SXE_VMOLR_MPE | SXE_VMOLR_ROMPE | SXE_VMOLR_ROPE);
+
+ sxe_hw_pool_rx_mode_set(hw, vm_l2_ctrl, vf_num);
+
+ sxe_hw_rx_mode_set(hw, filter_ctrl);
+
+ sxe_vlan_strip_switch_set(dev);
+}
+
+static inline void sxe_vf_flr_handle(struct rte_eth_dev *dev, u16 vf)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_vf_info *vf_info = adapter->vt_ctxt.vf_info;
+ u32 vm_l2_ctrl = sxe_hw_pool_rx_mode_get(hw, vf);
+
+ sxe_sw_uc_entry_vf_del(adapter, vf, false);
+
+ vm_l2_ctrl |= (SXE_VMOLR_AUPE | SXE_VMOLR_ROPE | SXE_VMOLR_BAM);
+
+ sxe_hw_pool_rx_mode_set(hw, vm_l2_ctrl, vf);
+
+ sxe_hw_tx_vlan_tag_clear(hw, vf);
+
+ vf_info[vf].mc_hash_used = 0;
+
+ sxe_filter_mode_configure(dev);
+}
+
+static void sxe_vf_promisc_mac_update(struct rte_eth_dev *dev, u32 vf,
+ u32 rar_idx)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_vf_info *vf_info = adapter->vt_ctxt.vf_info;
+ u16 vf_num = sxe_vf_num_get(dev);
+ u8 vf_idx;
+
+ for (vf_idx = 0; vf_idx < vf_num; vf_idx++) {
+ if (vf_info[vf_idx].cast_mode == SXE_CAST_MODE_PROMISC &&
+ vf_idx != vf)
+ sxe_hw_uc_addr_pool_enable(&adapter->hw, rar_idx, vf_idx);
+ }
+}
+
+static void sxe_vf_promisc_mac_update_all(struct rte_eth_dev *dev)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_vf_info *vf_info = adapter->vt_ctxt.vf_info;
+ struct sxe_uc_addr_table *uc_table = adapter->mac_filter_ctxt.uc_addr_table;
+ s32 i;
+ u16 vf_num = sxe_vf_num_get(dev);
+ u8 vf_idx;
+
+ for (vf_idx = 0; vf_idx < vf_num; vf_idx++) {
+ if (vf_info[vf_idx].cast_mode == SXE_CAST_MODE_PROMISC) {
+ for (i = 0; i < SXE_UC_ENTRY_NUM_MAX; i++) {
+ if (uc_table[i].used) {
+ sxe_hw_uc_addr_pool_enable(&adapter->hw,
+ uc_table[i].rar_idx, vf_idx);
+ }
+ }
+ }
+ }
+}
+
+static void sxe_vf_uc_clean(struct rte_eth_dev *dev, u32 vf)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_uc_addr_table *uc_table = adapter->mac_filter_ctxt.uc_addr_table;
+ struct sxe_vf_info *vf_info = &adapter->vt_ctxt.vf_info[vf];
+ u8 i;
+
+ sxe_sw_uc_entry_vf_del(adapter, vf, true);
+ for (i = 0; i < SXE_UC_ENTRY_NUM_MAX; i++) {
+ if (vf_info->uc_mac_table[i] == SXE_UC_MAC_SET)
+ sxe_hw_mac_reuse_del(dev, uc_table[i].addr, vf,
+ uc_table[i].rar_idx);
+ }
+ vf_info->uc_mac_cnt = 0;
+ memset(vf_info->uc_mac_table, SXE_UC_MAC_UNSET, SXE_UC_ENTRY_NUM_MAX);
+ sxe_vf_promisc_mac_update_all(dev);
+}
+
+static s32 sxe_vf_dev_mac_addr_set_handler(struct rte_eth_dev *dev, u32 *msgbuf, u32 vf)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_uc_addr_msg mac_msg = *(struct sxe_uc_addr_msg *)msgbuf;
+ struct sxe_vf_info *vf_info = adapter->vt_ctxt.vf_info;
+ u32 rar_idx = sxe_sw_uc_entry_vf_add(adapter, vf, mac_msg.uc_addr, false);
+ s32 ret = -SXE_ERR_PARAM;
+ u8 *mac_addr = mac_msg.uc_addr;
+
+ UNUSED(mac_addr);
+ if (rte_is_valid_assigned_ether_addr((struct rte_ether_addr *)mac_msg.uc_addr)) {
+ rte_memcpy(vf_info[vf].mac_addr, mac_msg.uc_addr, RTE_ETHER_ADDR_LEN);
+ ret = sxe_hw_uc_addr_add(&adapter->hw, rar_idx, mac_msg.uc_addr, vf);
+ if (ret) {
+ LOG_ERROR_BDF("vf:%u mac addr:" RTE_ETHER_ADDR_PRT_FMT " set fail.(err:%d)",
+ vf, mac_addr[0], mac_addr[1], mac_addr[2],
+ mac_addr[3], mac_addr[4], mac_addr[5], ret);
+ }
+ sxe_vf_promisc_mac_update(dev, vf, rar_idx);
+ }
+
+ return ret;
+}
+
+static s32 sxe_mbx_api_set_handler(struct rte_eth_dev *dev,
+ u32 *msg, u32 vf_idx)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_mbx_api_msg *api_msg = (struct sxe_mbx_api_msg *)msg;
+ struct sxe_vf_info *vf_info = &adapter->vt_ctxt.vf_info[vf_idx];
+ s32 ret = 0;
+
+ switch (api_msg->api_version) {
+ case SXE_MBX_API_10:
+ case SXE_MBX_API_11:
+ case SXE_MBX_API_12:
+ case SXE_MBX_API_13:
+ vf_info->mbx_version = api_msg->api_version;
+ break;
+ default:
+ ret = -SXE_ERR_PARAM;
+ LOG_ERROR_BDF("invalid mailbox api version:%u.",
+ api_msg->api_version);
+ break;
+ }
+
+ LOG_INFO_BDF("mailbox api version:0x%x.(err:%d)",
+ vf_info->mbx_version, ret);
+
+ return ret;
+}
+
+static s32 sxe_pf_ring_info_get(struct rte_eth_dev *dev, u32 *msgbuf, u32 vf)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_vf_info *vf_info = &adapter->vt_ctxt.vf_info[vf];
+ struct sxe_ring_info_msg *ring_msg = (struct sxe_ring_info_msg *)msgbuf;
+ u32 default_q = vf * RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool;
+ struct rte_eth_vmdq_dcb_tx_conf *vmdq_dcb_tx_conf;
+ u8 num_tcs;
+ u32 vmvir;
+ u32 vlan_action;
+ u32 vlan_id;
+ u32 user_priority;
+ s32 ret = 0;
+
+ switch (vf_info->mbx_version) {
+ case SXE_MBX_API_11:
+ case SXE_MBX_API_12:
+ case SXE_MBX_API_13:
+ break;
+ default:
+ ret = -SXE_ERR_CONFIG;
+ LOG_ERROR_BDF("mailbod version:0x%x not support get ring"
+ " info.(err:%d)",
+ vf_info->mbx_version, ret);
+ goto l_out;
+ }
+
+ ring_msg->max_rx_num = RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool;
+ ring_msg->max_tx_num = RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool;
+
+ ring_msg->default_tc = default_q;
+
+ switch (dev->data->dev_conf.txmode.mq_mode) {
+ case RTE_ETH_MQ_TX_NONE:
+ case RTE_ETH_MQ_TX_DCB:
+ ret = -SXE_ERR_CONFIG;
+ LOG_ERROR_BDF("vf_idx:%u sriov eanble, not support tx queue mode:0x%x.",
+ vf,
+ dev->data->dev_conf.txmode.mq_mode);
+ goto l_out;
+
+ case RTE_ETH_MQ_TX_VMDQ_DCB:
+ vmdq_dcb_tx_conf = &dev->data->dev_conf.tx_adv_conf.vmdq_dcb_tx_conf;
+ switch (vmdq_dcb_tx_conf->nb_queue_pools) {
+ case RTE_ETH_16_POOLS:
+ num_tcs = RTE_ETH_8_TCS;
+ break;
+ case RTE_ETH_32_POOLS:
+ num_tcs = RTE_ETH_4_TCS;
+ break;
+ default:
+ ret = -SXE_ERR_CONFIG;
+ LOG_ERROR_BDF("vf:%u sriov enable, tx queue mode:0x%x "
+ "invalid pool num:%u.(err:%d)",
+ vf,
+ dev->data->dev_conf.txmode.mq_mode,
+ vmdq_dcb_tx_conf->nb_queue_pools,
+ ret);
+ goto l_out;
+ }
+ break;
+
+ case RTE_ETH_MQ_TX_VMDQ_ONLY:
+ vmvir = sxe_hw_tx_vlan_insert_get(hw, vf);
+ vlan_action = vmvir & SXE_VMVIR_VLANA_MASK;
+ vlan_id = vmvir & SXE_VMVIR_VLAN_VID_MASK;
+ user_priority = (vmvir & SXE_VMVIR_VLAN_UP_MASK) >> VLAN_PRIO_SHIFT;
+ if (vlan_action == SXE_VMVIR_VLANA_DEFAULT &&
+ (vlan_id != 0 || user_priority != 0)) {
+ num_tcs = 1;
+ } else {
+ num_tcs = 0;
+ }
+ break;
+
+ default:
+ ret = -SXE_ERR_CONFIG;
+ LOG_ERROR_BDF("vf_idx:%u sriov eanble, invalid tx queue mode:0x%x.",
+ vf,
+ dev->data->dev_conf.txmode.mq_mode);
+ goto l_out;
+ }
+
+ ring_msg->tc_num = num_tcs;
+
+ LOG_INFO_BDF("max_rx_num:%u max_tx_num:%u default queue:%u tc_num:%u.",
+ ring_msg->max_rx_num, ring_msg->max_tx_num,
+ ring_msg->default_tc, ring_msg->tc_num);
+
+l_out:
+ return ret;
+}
+
+static s32 sxe_vf_rss_hash_conf_get(struct rte_eth_dev *dev, u32 *msgbuf, u32 vf)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct rte_eth_rss_conf rss_conf;
+ struct sxe_rss_hash_msg *rss_msg = (struct sxe_rss_hash_msg *)msgbuf;
+
+ UNUSED(vf);
+ rss_conf.rss_key = malloc(SXE_RSS_KEY_SIZE);
+ sxe_rss_hash_conf_get(dev, &rss_conf);
+
+ memcpy(rss_msg->hash_key, rss_conf.rss_key, SXE_RSS_KEY_SIZE);
+ rss_msg->rss_hf = rss_conf.rss_hf;
+
+ free(rss_conf.rss_key);
+
+ LOG_INFO_BDF("vf[%u] rss hash conf get, rss_key:%s, rss_hf:%" SXE_PRID64 "",
+ vf, rss_msg->hash_key, rss_msg->rss_hf);
+
+ return 0;
+}
+
+static s32 sxe_vf_vlan_id_set_handler(struct rte_eth_dev *dev,
+ u32 *msgbuf, u32 vf)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_vf_info *vf_info = adapter->vt_ctxt.vf_info;
+ struct sxe_vlan_msg *vlan_msg = (struct sxe_vlan_msg *)msgbuf;
+ u32 vlan_id = (vlan_msg->vlan_id & SXE_VLVF_VLANID_MASK);
+ s32 ret;
+
+ ret = sxe_hw_vlan_filter_configure(hw, vlan_id, vf, vlan_msg->add, false);
+ if (ret == 0) {
+ if (vlan_msg->add)
+ vf_info[vf].vlan_cnt++;
+ else if (vf_info[vf].vlan_cnt)
+ vf_info[vf].vlan_cnt--;
+ }
+
+ LOG_INFO_BDF("vf[%u] %s vid[%u] done vlan_cnt:%u ret = %d",
+ vf, vlan_msg->add ? "add" : "delete",
+ vlan_id,
+ vf_info[vf].vlan_cnt, ret);
+
+ return ret;
+}
+
+static s32 sxe_vf_max_frame_set_handler(struct rte_eth_dev *dev,
+ u32 *msgbuf, u32 vf)
+
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_vf_info *vf_info = &adapter->vt_ctxt.vf_info[vf];
+ struct sxe_max_frame_msg *msg = (struct sxe_max_frame_msg *)msgbuf;
+ u32 vf_max_frame = msg->max_frame + SXE_ETH_OVERHEAD;
+ s32 ret = 0;
+ u32 cur_max_frs;
+ u32 frame_size = SXE_GET_FRAME_SIZE(dev);
+
+ switch (vf_info->mbx_version) {
+ case SXE_MBX_API_11:
+ case SXE_MBX_API_12:
+ case SXE_MBX_API_13:
+ if (frame_size > SXE_ETH_MAX_LEN) {
+ LOG_WARN_BDF("pf jumbo frame enabled.");
+ break;
+ }
+ // fall through
+ default:
+ if (vf_max_frame > SXE_ETH_MAX_LEN ||
+ frame_size > SXE_ETH_MAX_LEN) {
+ ret = -SXE_ERR_PARAM;
+ LOG_ERROR_BDF("mbx version:0x%x pf max pkt len:0x%x vf:%u"
+ " max_frames:0x%x max_len:0x%x.(err:%d)",
+ vf_info->mbx_version,
+ frame_size,
+ vf, vf_max_frame,
+ SXE_ETH_MAX_LEN, ret);
+ goto l_out;
+ }
+ break;
+ }
+
+ if (vf_max_frame < RTE_ETHER_MIN_LEN ||
+ vf_max_frame > RTE_ETHER_MAX_JUMBO_FRAME_LEN) {
+ ret = -SXE_ERR_PARAM;
+ LOG_ERROR_BDF("mbx version:0x%x vf:%u invalid max_frame:%u (err:%d)",
+ vf_info->mbx_version,
+ vf,
+ vf_max_frame,
+ ret);
+ goto l_out;
+ }
+
+ cur_max_frs = sxe_hw_mac_max_frame_get(hw);
+ if (vf_max_frame > cur_max_frs) {
+ ret = -SXE_ERR_PARAM;
+ LOG_ERROR_BDF("mbx version:0x%x vf:%u invalid max_frame:%u >= cur_max_frs:%u",
+ vf_info->mbx_version,
+ vf,
+ vf_max_frame,
+ cur_max_frs);
+ goto l_out;
+ }
+
+l_out:
+ return ret;
+}
+
+static void sxe_vf_mc_promisc_disable(struct rte_eth_dev *dev, u32 vf)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ u32 vm_l2_ctrl = sxe_hw_pool_rx_mode_get(hw, vf);
+
+ vm_l2_ctrl &= ~SXE_VMOLR_MPE;
+
+ sxe_hw_pool_rx_mode_set(hw, vm_l2_ctrl, vf);
+}
+
+static void sxe_vf_promisc_disable(struct rte_eth_dev *dev, u32 vf)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_vf_info *vf_info = &adapter->vt_ctxt.vf_info[vf];
+ u32 disable;
+ u32 vm_l2_filter;
+
+ if (vf_info->cast_mode != SXE_CAST_MODE_PROMISC)
+ goto out;
+
+ disable = SXE_VMOLR_BAM | SXE_VMOLR_ROMPE |
+ SXE_VMOLR_MPE | SXE_VMOLR_ROPE;
+
+ vf_info->cast_mode = SXE_CAST_MODE_NONE;
+
+ vm_l2_filter = sxe_hw_pool_rx_mode_get(hw, vf);
+ vm_l2_filter &= ~disable;
+ sxe_hw_pool_rx_mode_set(hw, vm_l2_filter, vf);
+
+ adapter->vt_ctxt.promisc_cnt--;
+ if (adapter->vt_ctxt.promisc_cnt == 0)
+ sxe_uc_all_hash_table_set(dev, false);
+
+out:
+ return;
+}
+
+static s32 sxe_vf_mc_addr_sync(struct rte_eth_dev *dev,
+ u32 *msgbuf, u32 vf)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_vf_info *vf_info = &adapter->vt_ctxt.vf_info[vf];
+ struct sxe_mc_sync_msg *mc_msg = (struct sxe_mc_sync_msg *)msgbuf;
+ u8 mc_cnt = min(mc_msg->mc_cnt, SXE_VF_MC_ENTRY_NUM_MAX);
+ u32 mta_idx;
+ u32 mta_shift;
+ u32 vm_l2_filter = sxe_hw_pool_rx_mode_get(hw, vf);
+ int i;
+
+ sxe_vf_mc_promisc_disable(dev, vf);
+
+ vf_info->mc_hash_used = mc_cnt;
+ for (i = 0; i < mc_cnt; i++) {
+ vf_info->mc_hash[i] = mc_msg->mc_addr_extract[i];
+ LOG_INFO_BDF("vf_idx:%u mc_cnt:%u mc_hash[%d]:0x%x",
+ vf, mc_cnt, i, vf_info->mc_hash[i]);
+ }
+
+ if (mc_cnt == 0) {
+ vm_l2_filter &= ~SXE_VMOLR_ROMPE;
+ sxe_hw_pool_rx_mode_set(hw, vm_l2_filter, vf);
+ LOG_WARN_BDF("vf:%u request disable mta filter.", vf);
+ } else {
+ for (i = 0; i < mc_cnt; i++) {
+ mta_idx = (vf_info->mc_hash[i] >> SXE_MC_ADDR_SHIFT) &
+ SXE_MC_ADDR_REG_MASK;
+ mta_shift = vf_info->mc_hash[i] & SXE_MC_ADDR_BIT_MASK;
+ sxe_hw_mta_hash_table_update(hw, mta_idx, mta_shift);
+
+ LOG_INFO_BDF("vf_idx:%u mc_cnt:%u mc_hash[%d]:0x%x "
+ "reg_idx=%u, bit_idx=%u.",
+ vf, mc_cnt, i, vf_info->mc_hash[i],
+ mta_idx, mta_shift);
+ }
+
+ vm_l2_filter |= SXE_VMOLR_ROMPE;
+ sxe_hw_pool_rx_mode_set(hw, vm_l2_filter, vf);
+ sxe_hw_mc_filter_enable(hw);
+ }
+
+ return 0;
+}
+
+static void sxe_vf_mac_reuse_rebuild(struct sxe_adapter *adapter,
+ u8 rar_idx, u32 vf)
+{
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_vf_info *vf_info = &adapter->vt_ctxt.vf_info[vf];
+ struct sxe_uc_addr_table *uc_table = adapter->mac_filter_ctxt.uc_addr_table;
+ u8 i;
+
+ for (i = 0; i < SXE_UC_ENTRY_NUM_MAX; i++) {
+ if (vf_info->uc_mac_table[i] == SXE_UC_MAC_SET &&
+ memcmp(uc_table[rar_idx].addr, uc_table[rar_idx].addr,
+ SXE_MAC_ADDR_LEN) == 0) {
+ sxe_hw_uc_addr_pool_enable(hw, rar_idx, vf);
+ break;
+ }
+ }
+}
+
+static s32 sxe_vf_cast_mode_handler(struct rte_eth_dev *dev,
+ u32 *msgbuf, u32 vf)
+
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_vf_info *vf_info = &adapter->vt_ctxt.vf_info[vf];
+ struct sxe_cast_mode_msg *cast_msg = (struct sxe_cast_mode_msg *)msgbuf;
+ struct sxe_uc_addr_table *uc_table = adapter->mac_filter_ctxt.uc_addr_table;
+ u32 enable;
+ u32 disable;
+ u32 flt_ctrl = 0;
+ u32 vm_l2_filter;
+ s32 ret = 0;
+ u8 i;
+ bool allmulti = false;
+
+ switch (vf_info->mbx_version) {
+ case SXE_MBX_API_12:
+ case SXE_MBX_API_13:
+ break;
+ default:
+ ret = -SXE_ERR_PARAM;
+ LOG_ERROR_BDF("vf:%u invalid mbx api version:0x%x.",
+ vf, vf_info->mbx_version);
+ goto l_out;
+ }
+
+ if (vf_info->cast_mode == cast_msg->cast_mode) {
+ LOG_INFO_BDF("vf:%d currut mode equal set mode:0x%x, skip set.",
+ vf, cast_msg->cast_mode);
+ goto l_out;
+ }
+
+ switch (cast_msg->cast_mode) {
+ case SXE_CAST_MODE_NONE:
+ disable = SXE_VMOLR_BAM | SXE_VMOLR_ROMPE |
+ SXE_VMOLR_MPE | SXE_VMOLR_ROPE;
+ enable = 0;
+ break;
+
+ case SXE_CAST_MODE_MULTI:
+ disable = SXE_VMOLR_MPE | SXE_VMOLR_ROPE;
+ enable = SXE_VMOLR_BAM | SXE_VMOLR_ROMPE;
+ break;
+
+ case SXE_CAST_MODE_ALLMULTI:
+ disable = SXE_VMOLR_ROPE;
+ enable = SXE_VMOLR_BAM | SXE_VMOLR_ROMPE |
+ SXE_VMOLR_MPE;
+ allmulti = true;
+ break;
+
+ case SXE_CAST_MODE_PROMISC:
+ disable = 0;
+ enable = SXE_VMOLR_MPE | SXE_VMOLR_ROPE |
+ SXE_VMOLR_BAM | SXE_VMOLR_ROMPE;
+ allmulti = true;
+ break;
+
+ default:
+ ret = -SXE_ERR_PARAM;
+ LOG_ERROR_BDF("vf:%u invalid cast mode:0x%x.",
+ vf, cast_msg->cast_mode);
+ goto l_out;
+ }
+
+ vm_l2_filter = sxe_hw_pool_rx_mode_get(hw, vf);
+ vm_l2_filter &= ~disable;
+ vm_l2_filter |= enable;
+ sxe_hw_pool_rx_mode_set(hw, vm_l2_filter, vf);
+
+ if (allmulti) {
+ flt_ctrl = sxe_hw_rx_mode_get(hw) | SXE_FCTRL_MPE;
+ sxe_hw_rx_mode_set(hw, flt_ctrl);
+ }
+
+ if (cast_msg->cast_mode == SXE_CAST_MODE_PROMISC) {
+ sxe_uc_all_hash_table_set(dev, true);
+ adapter->vt_ctxt.promisc_cnt++;
+ for (i = 0; i < SXE_UC_ENTRY_NUM_MAX; i++) {
+ if (uc_table[i].used)
+ sxe_hw_uc_addr_pool_enable(hw, i, vf);
+ }
+ } else if (vf_info->cast_mode == SXE_CAST_MODE_PROMISC) {
+ adapter->vt_ctxt.promisc_cnt--;
+ if (adapter->vt_ctxt.promisc_cnt == 0)
+ sxe_uc_all_hash_table_set(dev, false);
+
+ for (i = 0; i < SXE_UC_ENTRY_NUM_MAX; i++) {
+ if (uc_table[i].used && uc_table[i].pool_idx != vf) {
+ sxe_hw_uc_addr_pool_del(hw, i, vf);
+ sxe_vf_mac_reuse_rebuild(adapter, i, vf);
+ }
+ }
+ }
+
+ vf_info->cast_mode = cast_msg->cast_mode;
+ LOG_INFO_BDF("vf:%d filter reg:0x%x mode:%d promisc vfs:%d.",
+ vf, vm_l2_filter, cast_msg->cast_mode, adapter->vt_ctxt.promisc_cnt);
+
+l_out:
+ return ret;
+}
+
+static s32 sxe_vf_uc_addr_sync_handler(struct rte_eth_dev *dev,
+ u32 *msgbuf, u32 vf)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_vf_info *vf_info = &adapter->vt_ctxt.vf_info[vf];
+ struct sxe_uc_sync_msg *uc_msg = (struct sxe_uc_sync_msg *)msgbuf;
+ s32 ret = 0;
+ u8 rar_idx;
+ u8 *mac_addr = (u8 *)uc_msg->addr;
+
+ UNUSED(mac_addr);
+ if (uc_msg->index) {
+ if (!rte_is_valid_assigned_ether_addr((struct rte_ether_addr *)uc_msg->addr)) {
+ ret = -SXE_ERR_PARAM;
+ LOG_ERROR_BDF("vf:%u mac addr:" RTE_ETHER_ADDR_PRT_FMT " invalid.(err:%d).",
+ vf, mac_addr[0], mac_addr[1], mac_addr[2],
+ mac_addr[3], mac_addr[4], mac_addr[5], ret);
+ goto l_out;
+ }
+
+ vf_info->uc_mac_cnt++;
+ rar_idx = sxe_sw_uc_entry_vf_add(adapter, vf, (u8 *)uc_msg->addr, true);
+ if (rar_idx < SXE_UC_ENTRY_NUM_MAX) {
+ vf_info->uc_mac_table[rar_idx] = SXE_UC_MAC_SET;
+ sxe_hw_uc_addr_add(hw, rar_idx, (u8 *)uc_msg->addr, vf);
+ sxe_hw_mac_reuse_add(dev, (u8 *)uc_msg->addr, rar_idx);
+ sxe_vf_promisc_mac_update(dev, vf, rar_idx);
+ }
+ } else {
+ if (vf_info->uc_mac_cnt)
+ sxe_vf_uc_clean(dev, vf);
+ }
+
+ LOG_INFO_BDF("vf:%u mac addr:" RTE_ETHER_ADDR_PRT_FMT " opt:%d.",
+ vf, mac_addr[0], mac_addr[1], mac_addr[2],
+ mac_addr[3], mac_addr[4], mac_addr[5], uc_msg->index);
+
+l_out:
+ return ret;
+}
+
+static struct sxe_msg_table msg_table[] = {
+ [SXE_VFREQ_MAC_ADDR_SET] = {SXE_VFREQ_MAC_ADDR_SET, sxe_vf_dev_mac_addr_set_handler},
+ [SXE_VFREQ_MC_ADDR_SYNC] = {SXE_VFREQ_MC_ADDR_SYNC, sxe_vf_mc_addr_sync},
+ [SXE_VFREQ_VLAN_SET] = {SXE_VFREQ_VLAN_SET, sxe_vf_vlan_id_set_handler},
+ [SXE_VFREQ_LPE_SET] = {SXE_VFREQ_LPE_SET, sxe_vf_max_frame_set_handler},
+ [SXE_VFREQ_UC_ADDR_SYNC] = {SXE_VFREQ_UC_ADDR_SYNC, sxe_vf_uc_addr_sync_handler},
+ [SXE_VFREQ_API_NEGOTIATE] = {SXE_VFREQ_API_NEGOTIATE, sxe_mbx_api_set_handler},
+ [SXE_VFREQ_RING_INFO_GET] = {SXE_VFREQ_RING_INFO_GET, sxe_pf_ring_info_get},
+ [SXE_VFREQ_CAST_MODE_SET] = {SXE_VFREQ_CAST_MODE_SET, sxe_vf_cast_mode_handler},
+ [SXE_VFREQ_RSS_CONF_GET] = {SXE_VFREQ_RSS_CONF_GET, sxe_vf_rss_hash_conf_get},
+};
+
+static void sxe_vf_pool_enable(struct rte_eth_dev *dev, u8 vf_idx)
+{
+ u32 enable_pool;
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ u8 reg_idx = vf_idx / 32;
+ u8 bit_idx = vf_idx % 32;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_vf_info *vf_info = &adapter->vt_ctxt.vf_info[vf_idx];
+
+ enable_pool = sxe_hw_tx_pool_bitmap_get(hw, reg_idx);
+ enable_pool |= BIT(bit_idx);
+ sxe_hw_tx_pool_bitmap_set(hw, reg_idx, enable_pool);
+
+ sxe_hw_vf_queue_drop_enable(hw, vf_idx,
+ RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool);
+
+ enable_pool = sxe_hw_rx_pool_bitmap_get(hw, reg_idx);
+ enable_pool |= BIT(bit_idx);
+ sxe_hw_rx_pool_bitmap_set(hw, reg_idx, enable_pool);
+
+ vf_info->is_ready = true;
+
+ sxe_hw_spoof_count_enable(hw, reg_idx, bit_idx);
+}
+
+static void sxe_vf_reset_msg_handle(struct rte_eth_dev *dev, u8 vf_idx)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_rst_reply reply = {};
+ u8 *mac_addr = adapter->vt_ctxt.vf_info[vf_idx].mac_addr;
+ u8 *addr_bytes = (u8 *)(((struct rte_ether_addr *)mac_addr)->addr_bytes);
+ u32 rar_idx = sxe_sw_uc_entry_vf_add(adapter, vf_idx, addr_bytes, false);
+
+ LOG_INFO_BDF("receive vf_idx:%d reset msg.", vf_idx);
+
+ sxe_vf_pool_enable(dev, vf_idx);
+
+ sxe_vf_flr_handle(dev, vf_idx);
+
+ sxe_hw_uc_addr_add(&adapter->hw, rar_idx, addr_bytes, vf_idx);
+
+ sxe_vf_mc_promisc_disable(dev, vf_idx);
+
+ sxe_vf_promisc_disable(dev, vf_idx);
+
+ reply.msg_type = SXE_VFREQ_RESET | SXE_MSGTYPE_ACK;
+ reply.mc_filter_type = SXE_MC_FILTER_TYPE0;
+ rte_memcpy(reply.mac_addr, mac_addr, RTE_ETHER_ADDR_LEN);
+
+ sxe_hw_send_msg_to_vf(hw, (u32 *)&reply,
+ SXE_MSG_NUM(sizeof(reply)), vf_idx);
+
+ adapter->vt_ctxt.vf_info->is_ready = true;
+
+ LOG_INFO_BDF("vf_idx:%d reset msg:0x%x handle done.send mac addr:" RTE_ETHER_ADDR_PRT_FMT
+ " mc type:%d to vf.",
+ vf_idx, reply.msg_type,
+ mac_addr[0], mac_addr[1], mac_addr[2],
+ mac_addr[3], mac_addr[4], mac_addr[5],
+ SXE_MC_FILTER_TYPE0);
+}
+
+static s32 sxe_req_msg_handle(struct rte_eth_dev *dev, u32 *msg,
+ u8 vf_idx)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ s32 ret = 0;
+ u16 cmd_id = msg[0] & SXE_VFREQ_MASK;
+ struct rte_pmd_sxe_mb_event_param user_param;
+
+ if (cmd_id > SXE_VFREQ_CAST_MODE_SET &&
+ cmd_id <= SXE_VFREQ_IPSEC_DEL) {
+ ret = -SXE_ERR_PARAM;
+ LOG_ERROR_BDF("vf_idx:%u msg:0x%x invalid cmd_id:0x%x.",
+ vf_idx, msg[0], cmd_id);
+ goto l_out;
+ }
+
+ user_param.ret = RTE_PMD_SXE_MB_EVENT_PROCEED;
+ user_param.vf_idx = vf_idx;
+ user_param.msg_type = msg[0] & 0xFFFF;
+ user_param.msg = (void *)msg;
+
+ if (cmd_id == SXE_VFREQ_RESET) {
+ ret = 0;
+ sxe_vf_reset_msg_handle(dev, vf_idx);
+
+ sxe_eth_dev_callback_process(dev, RTE_ETH_EVENT_VF_MBOX,
+ &user_param);
+ goto l_out;
+ }
+
+ sxe_eth_dev_callback_process(dev, RTE_ETH_EVENT_VF_MBOX,
+ &user_param);
+
+ LOG_INFO_BDF("vf_idx:%u cmd_id:0x%x user configure:0x%x.",
+ vf_idx, cmd_id, user_param.ret);
+
+ if (!adapter->vt_ctxt.vf_info[vf_idx].is_ready) {
+ msg[0] |= SXE_MSGTYPE_NACK;
+ ret = sxe_hw_send_msg_to_vf(hw, msg,
+ SXE_MSG_NUM(sizeof(msg[0])), vf_idx);
+ LOG_WARN_BDF("vf_idx:%d not ready now, send nack to vf.ret:%d.",
+ vf_idx, ret);
+ goto l_out;
+ }
+
+ if (msg_table[cmd_id].msg_func) {
+ if (user_param.ret == RTE_PMD_SXE_MB_EVENT_PROCEED ||
+ cmd_id == SXE_VFREQ_API_NEGOTIATE ||
+ cmd_id == SXE_VFREQ_RING_INFO_GET) {
+ ret = msg_table[cmd_id].msg_func(dev, msg, vf_idx);
+ }
+ LOG_INFO_BDF("msg:0x%x cmd_id:0x%x handle done.ret:%d",
+ msg[0], cmd_id, ret);
+ } else {
+ ret = -SXE_ERR_PARAM;
+ }
+
+ if (!ret) {
+ msg[0] |= SXE_MSGTYPE_ACK;
+ } else {
+ msg[0] |= SXE_MSGTYPE_NACK;
+ LOG_ERROR_BDF("vf_idx:%u msg_type:0x%x cmdId:0x%x invalid.(err:%d)",
+ vf_idx, msg[0], cmd_id, ret);
+ }
+
+ ret = sxe_hw_send_msg_to_vf(hw, msg, SXE_MBX_MSG_NUM, vf_idx);
+ if (ret) {
+ LOG_ERROR_BDF("vf:%d msg:0x%x reply fail.(err:%d).",
+ vf_idx, msg[0], ret);
+ }
+
+ LOG_INFO_BDF("pf reply vf:%d msg:0x%x done.ret:%d", vf_idx, msg[0], ret);
+
+l_out:
+ return ret;
+}
+
+static s32 sxe_vf_req_msg_handle(struct rte_eth_dev *dev, u8 vf_idx)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ u32 msg[SXE_MBX_MSG_NUM] = {0};
+ s32 ret;
+
+ ret = sxe_hw_rcv_msg_from_vf(hw, msg, SXE_MBX_MSG_NUM, vf_idx);
+ if (ret) {
+ LOG_ERROR_BDF("rcv vf:0x%x req msg:0x%x fail.(err:%d)",
+ vf_idx, msg[0], ret);
+ goto l_out;
+ }
+
+ LOG_INFO_BDF("rcv vf_idx:%d req msg:0x%x.", vf_idx, msg[0]);
+
+ if (msg[0] & (SXE_MSGTYPE_ACK | SXE_MSGTYPE_NACK)) {
+ LOG_WARN_BDF("msg:0x%x has handled, no need dup handle.",
+ msg[0]);
+ goto l_out;
+ }
+
+ ret = sxe_req_msg_handle(dev, msg, vf_idx);
+ if (ret) {
+ LOG_ERROR_BDF("vf:%d request msg handle fail.(err:%d)",
+ vf_idx, ret);
+ }
+
+l_out:
+ return ret;
+}
+
+static void sxe_vf_ack_msg_handle(struct rte_eth_dev *eth_dev, u8 vf_idx)
+{
+ struct sxe_adapter *adapter = eth_dev->data->dev_private;
+ u32 msg = SXE_MSGTYPE_NACK;
+
+ if (!adapter->vt_ctxt.vf_info[vf_idx].is_ready) {
+ sxe_hw_send_msg_to_vf(&adapter->hw, &msg,
+ SXE_MSG_NUM(sizeof(msg)), vf_idx);
+ }
+}
+
+void sxe_mbx_irq_handler(struct rte_eth_dev *eth_dev)
+{
+ struct sxe_adapter *adapter = eth_dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ u16 vf_num = sxe_vf_num_get(eth_dev);
+ u8 vf_idx;
+
+ LOG_DEBUG_BDF("mailbox irq triggered vf_num:%u.", vf_num);
+
+ for (vf_idx = 0; vf_idx < vf_num; vf_idx++) {
+ if (sxe_hw_vf_rst_check(hw, vf_idx)) {
+ LOG_WARN_BDF("vf_idx:%d flr triggered.", vf_idx);
+ sxe_vf_flr_handle(eth_dev, vf_idx);
+ }
+
+ if (sxe_hw_vf_req_check(hw, vf_idx))
+ sxe_vf_req_msg_handle(eth_dev, vf_idx);
+
+ if (sxe_hw_vf_ack_check(hw, vf_idx))
+ sxe_vf_ack_msg_handle(eth_dev, vf_idx);
+ }
+}
+
+int rte_pmd_sxe_set_vf_rxmode(u16 port, u16 vf,
+ u16 rx_mask, u8 on)
+{
+ u32 val = 0;
+ struct rte_eth_dev *dev;
+ struct rte_pci_device *pci_dev;
+ struct sxe_adapter *adapter;
+ struct sxe_hw *hw;
+ u32 vmolr;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+ dev = &rte_eth_devices[port];
+ pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+
+ if (!is_sxe_supported(dev))
+ return -ENOTSUP;
+
+ if (vf >= pci_dev->max_vfs)
+ return -EINVAL;
+
+ if (on > 1)
+ return -EINVAL;
+
+ adapter = dev->data->dev_private;
+ hw = &adapter->hw;
+ vmolr = sxe_hw_pool_rx_mode_get(hw, vf);
+
+ if (sxe_hw_vt_status(hw) == false)
+ return -ENOTSUP;
+
+ sxe_vmdq_rx_mode_get((u32)rx_mask, &val);
+
+ if (on)
+ vmolr |= val;
+ else
+ vmolr &= ~val;
+
+ sxe_hw_pool_rx_mode_set(hw, vmolr, vf);
+
+ return 0;
+}
+
+#ifdef ETH_DEV_MIRROR_RULE
+static s32 sxe_mirror_conf_check(struct sxe_hw *hw, u8 rule_id,
+ u8 rule_type)
+{
+ s32 ret = 0;
+
+ if (sxe_hw_vt_status(hw) == 0) {
+ ret = -ENOTSUP;
+ PMD_LOG_ERR(DRV, "virtual disabled, mirror rule not support.(err:%d)",
+ ret);
+ goto l_out;
+ }
+
+ if (rule_id >= SXE_MIRROR_RULES_MAX) {
+ ret = -EINVAL;
+ PMD_LOG_ERR(DRV, "invalid rule_id:%u rule id max:%u.(err:%d)",
+ rule_id, SXE_MIRROR_RULES_MAX, ret);
+ goto l_out;
+ }
+
+ if (SXE_MIRROR_TYPE_INVALID(rule_type)) {
+ ret = -EINVAL;
+ PMD_LOG_ERR(DRV, "unsupported mirror type 0x%x.(err:%d)",
+ rule_type, ret);
+ }
+
+l_out:
+ return ret;
+}
+
+static s32 sxe_vlan_mirror_configure(struct rte_eth_dev *dev,
+ struct rte_eth_mirror_conf *mirror_conf,
+ u8 rule_id, u8 on)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_mirror_info *mirror_info = &adapter->vt_ctxt.mr_info;
+ u32 mv_msb = 0;
+ u32 mv_lsb = 0;
+ u64 vlan_mask = 0;
+ u32 vlvf;
+ u8 i;
+ u8 reg_idx;
+ s32 ret = 0;
+
+ for (i = 0; i < ETH_VMDQ_MAX_VLAN_FILTERS; i++) {
+ if (mirror_conf->vlan.vlan_mask & (1ULL << i)) {
+ ret = sxe_hw_vlvf_slot_find(hw,
+ mirror_conf->vlan.vlan_id[i],
+ false);
+ if (ret < 0) {
+ ret = -EINVAL;
+ LOG_ERROR_BDF("vlan_id[%u]:0x%x no matched vlvf."
+ "(err:%d)",
+ i,
+ mirror_conf->vlan.vlan_id[i],
+ ret);
+ goto l_out;
+ }
+
+ reg_idx = ret;
+ vlvf = sxe_hw_vlan_pool_filter_read(hw, reg_idx);
+ if ((vlvf & SXE_VLVF_VIEN) &&
+ ((vlvf & SXE_VLVF_VLANID_MASK) ==
+ mirror_conf->vlan.vlan_id[i])) {
+ vlan_mask |= (1ULL << reg_idx);
+ } else{
+ ret = -EINVAL;
+ LOG_ERROR_BDF("i:%u vlan_id:0x%x "
+ "vlvf[%u]:0x%x not meet request."
+ "(err:%d)",
+ i,
+ mirror_conf->vlan.vlan_id[i],
+ reg_idx,
+ vlvf,
+ ret);
+ goto l_out;
+ }
+ }
+ }
+
+ if (on) {
+ mv_lsb = vlan_mask & SXE_MR_VLAN_MASK;
+ mv_msb = vlan_mask >> SXE_MR_VLAN_MSB_BIT_OFFSET;
+
+ mirror_info->mr_conf[rule_id].vlan.vlan_mask =
+ mirror_conf->vlan.vlan_mask;
+
+ for (i = 0; i < ETH_VMDQ_MAX_VLAN_FILTERS; i++) {
+ if (mirror_conf->vlan.vlan_mask & (1ULL << i)) {
+ mirror_info->mr_conf[rule_id].vlan.vlan_id[i] =
+ mirror_conf->vlan.vlan_id[i];
+ LOG_INFO_BDF("rule_id:%u vlan id:0x%x add mirror"
+ " to dst_pool:%u",
+ rule_id,
+ mirror_conf->vlan.vlan_id[i],
+ mirror_conf->dst_pool);
+ }
+ }
+ } else {
+ mv_lsb = 0;
+ mv_msb = 0;
+ mirror_info->mr_conf[rule_id].vlan.vlan_mask = 0;
+
+ for (i = 0; i < ETH_VMDQ_MAX_VLAN_FILTERS; i++) {
+ mirror_info->mr_conf[rule_id].vlan.vlan_id[i] = 0;
+ LOG_INFO_BDF("rule_id:%u vlan id:0x%x del mirror"
+ " from dst_pool:%u",
+ rule_id,
+ mirror_conf->vlan.vlan_id[i],
+ mirror_conf->dst_pool);
+ }
+ }
+
+ sxe_hw_mirror_vlan_set(hw, rule_id, mv_lsb, mv_msb);
+
+l_out:
+ return ret;
+}
+
+static void sxe_virtual_pool_mirror_configure(struct rte_eth_dev *dev,
+ struct rte_eth_mirror_conf *mirror_conf,
+ u8 rule_id, u8 on)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_mirror_info *mirror_info = &adapter->vt_ctxt.mr_info;
+ u32 lsb = 0;
+ u32 msb = 0;
+
+ if (on) {
+ lsb = mirror_conf->pool_mask & SXE_MR_VIRTUAL_POOL_MASK;
+ msb = mirror_conf->pool_mask >> SXE_MR_VIRTUAL_POOL_MSB_BIT_MASK;
+ mirror_info->mr_conf[rule_id].pool_mask = mirror_conf->pool_mask;
+ } else {
+ lsb = 0;
+ msb = 0;
+ mirror_info->mr_conf[rule_id].pool_mask = 0;
+ }
+
+ sxe_hw_mirror_virtual_pool_set(hw, rule_id, lsb, msb);
+}
+
+s32 sxe_mirror_rule_set(struct rte_eth_dev *dev,
+ struct rte_eth_mirror_conf *mirror_conf,
+ u8 rule_id, u8 on)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_mirror_info *mirror_info = &adapter->vt_ctxt.mr_info;
+ u8 mirror_type = 0;
+ s32 ret;
+
+ ret = sxe_mirror_conf_check(hw, rule_id, mirror_conf->rule_type);
+ if (ret) {
+ LOG_ERROR_BDF("rule_id:%u mirror config param invalid.(err:%d)",
+ rule_id, ret);
+ goto l_out;
+ }
+
+ if (mirror_conf->rule_type & ETH_MIRROR_VLAN) {
+ mirror_type |= SXE_MRCTL_VLME;
+ ret = sxe_vlan_mirror_configure(dev, mirror_conf, rule_id, on);
+ if (ret) {
+ LOG_ERROR_BDF("vlan mirror configure fail.(err:%d)", ret);
+ goto l_out;
+ }
+ }
+
+ if (mirror_conf->rule_type & ETH_MIRROR_VIRTUAL_POOL_UP) {
+ mirror_type |= SXE_MRCTL_VPME;
+ sxe_virtual_pool_mirror_configure(dev, mirror_conf, rule_id, on);
+ }
+
+ if (mirror_conf->rule_type & ETH_MIRROR_UPLINK_PORT)
+ mirror_type |= SXE_MRCTL_UPME;
+
+ if (mirror_conf->rule_type & ETH_MIRROR_DOWNLINK_PORT)
+ mirror_type |= SXE_MRCTL_DPME;
+
+ sxe_hw_mirror_ctl_set(hw, rule_id, mirror_type, mirror_conf->dst_pool, on);
+
+ mirror_info->mr_conf[rule_id].rule_type = mirror_conf->rule_type;
+ mirror_info->mr_conf[rule_id].dst_pool = mirror_conf->dst_pool;
+
+ LOG_INFO_BDF("rule_id:%u mirrror type:0x%x %s success. "
+ "vlan id mask:0x%" SXE_PRIX64 " virtual pool mask:0x%" SXE_PRIX64
+ " dst_pool:%u.",
+ rule_id,
+ mirror_conf->rule_type,
+ on ? "add" : "delete",
+ mirror_conf->vlan.vlan_mask,
+ mirror_conf->pool_mask,
+ mirror_conf->dst_pool);
+
+l_out:
+ return ret;
+}
+
+s32 sxe_mirror_rule_reset(struct rte_eth_dev *dev, u8 rule_id)
+{
+ struct sxe_adapter *adapter = dev->data->dev_private;
+ struct sxe_hw *hw = &adapter->hw;
+ struct sxe_mirror_info *mirror_info = &adapter->vt_ctxt.mr_info;
+ s32 ret;
+
+ ret = sxe_mirror_conf_check(hw, rule_id, SXE_ETH_MIRROR_TYPE_MASK);
+ if (ret) {
+ LOG_ERROR_BDF("rule_id:%u mirror config param invalid.(err:%d)",
+ rule_id, ret);
+ goto l_out;
+ }
+
+ memset(&mirror_info->mr_conf[rule_id], 0,
+ sizeof(struct rte_eth_mirror_conf));
+
+ sxe_hw_mirror_rule_clear(hw, rule_id);
+
+ LOG_INFO_BDF("rule_id:%u reset susccess.", rule_id);
+
+l_out:
+ return ret;
+}
+
+#endif
+#endif
diff --git a/drivers/net/sxe/pf/sxe_vf.h b/drivers/net/sxe/pf/sxe_vf.h
new file mode 100644
index 0000000000..05b91540cc
--- /dev/null
+++ b/drivers/net/sxe/pf/sxe_vf.h
@@ -0,0 +1,219 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#ifndef __SXE_VF_H__
+#define __SXE_VF_H__
+
+#include "sxe_dpdk_version.h"
+#include <rte_ethdev.h>
+#include <bus_pci_driver.h>
+
+#include "sxe_hw.h"
+
+#define SXE_MIRROR_RULES_MAX 4
+
+#define SXE_MSG_NUM(size) DIV_ROUND_UP(size, 4)
+
+#define SXE_MSGTYPE_ACK 0x80000000
+#define SXE_MSGTYPE_NACK 0x40000000
+
+#define SXE_VFREQ_RESET 0x01
+#define SXE_VFREQ_MAC_ADDR_SET 0x02
+#define SXE_VFREQ_MC_ADDR_SYNC 0x03
+#define SXE_VFREQ_VLAN_SET 0x04
+#define SXE_VFREQ_LPE_SET 0x05
+
+#define SXE_VFREQ_UC_ADDR_SYNC 0x06
+
+#define SXE_VFREQ_API_NEGOTIATE 0x08
+
+#define SXE_VFREQ_RING_INFO_GET 0x09
+#define SXE_VFREQ_REDIR_TBL_GET 0x0a
+#define SXE_VFREQ_RSS_KEY_GET 0x0b
+#define SXE_VFREQ_CAST_MODE_SET 0x0c
+#define SXE_VFREQ_LINK_ENABLE_GET 0X0d
+#define SXE_VFREQ_IPSEC_ADD 0x0e
+#define SXE_VFREQ_IPSEC_DEL 0x0f
+#define SXE_VFREQ_RSS_CONF_GET 0x10
+
+#define SXE_VFREQ_MASK 0xFF
+
+#define SXE_MIRROR_TYPE_INVALID(mirror_type) \
+ ((mirror_type) & ~(u8)(ETH_MIRROR_VIRTUAL_POOL_UP | \
+ ETH_MIRROR_UPLINK_PORT | ETH_MIRROR_DOWNLINK_PORT | ETH_MIRROR_VLAN))
+
+#define SXE_ETH_MIRROR_TYPE_MASK \
+ (ETH_MIRROR_VIRTUAL_POOL_UP | ETH_MIRROR_UPLINK_PORT \
+ | ETH_MIRROR_DOWNLINK_PORT | ETH_MIRROR_VLAN)
+
+static inline u16 sxe_vf_num_get(struct rte_eth_dev *eth_dev)
+{
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+
+ return pci_dev->max_vfs;
+}
+
+enum sxe_mbx_api_version {
+ SXE_MBX_API_10 = 0,
+ SXE_MBX_API_11,
+ SXE_MBX_API_12,
+ SXE_MBX_API_13,
+ SXE_MBX_API_14,
+
+ SXE_MBX_API_NR,
+};
+
+enum sxe_cast_mode {
+ SXE_CAST_MODE_NONE = 0,
+ SXE_CAST_MODE_MULTI,
+ SXE_CAST_MODE_ALLMULTI,
+ SXE_CAST_MODE_PROMISC,
+};
+
+struct sxe_vf_info {
+ u8 mac_addr[RTE_ETHER_ADDR_LEN];
+ u16 mc_hash[SXE_VF_MC_ENTRY_NUM_MAX];
+ u8 mc_hash_used;
+ u8 cast_mode;
+ u8 trusted :1;
+ u8 is_ready :1;
+ u8 spoof_chk_enabled :1;
+ u8 rss_query_enabled :1;
+ u8 mac_from_pf :1;
+ u8 reserved :3;
+ u16 domain_id;
+ u16 tx_rate;
+ u32 mbx_version;
+ u32 vlan_cnt;
+ u32 uc_mac_cnt;
+ u8 uc_mac_table[SXE_UC_ENTRY_NUM_MAX];
+};
+
+#ifdef ETH_DEV_MIRROR_RULE
+struct sxe_mirror_info {
+ struct rte_eth_mirror_conf mr_conf[SXE_MIRROR_RULES_MAX];
+
+};
+#endif
+
+struct sxe_virtual_context {
+ u8 pflink_fullchk;
+ u8 promisc_cnt;
+ u32 mbx_version;
+ struct sxe_vf_info *vf_info;
+#ifdef ETH_DEV_MIRROR_RULE
+ struct sxe_mirror_info mr_info;
+#endif
+};
+
+struct sxe_msg_table {
+ u32 msg_type;
+ s32 (*msg_func)(struct rte_eth_dev *dev, u32 *msg, u32 vf_idx);
+};
+
+enum RTE_PMD_SXE_MB_event_rsp {
+ RTE_PMD_SXE_MB_EVENT_NOOP_ACK,
+ RTE_PMD_SXE_MB_EVENT_NOOP_NACK,
+ RTE_PMD_SXE_MB_EVENT_PROCEED,
+ RTE_PMD_SXE_MB_EVENT_MAX
+};
+
+struct rte_pmd_sxe_mb_event_param {
+ u16 vf_idx;
+ u16 msg_type;
+ u16 ret;
+ void *msg;
+};
+
+struct sxe_mbx_api_msg {
+ u32 msg_type;
+ u32 api_version;
+};
+
+struct sxe_uc_addr_msg {
+ u32 msg_type;
+ u8 uc_addr[RTE_ETHER_ADDR_LEN];
+ u16 pad;
+};
+
+struct sxe_rst_rcv {
+ u32 msg_type;
+};
+
+struct sxe_rst_reply {
+ u32 msg_type;
+ u32 mac_addr[2];
+ u32 mc_filter_type;
+};
+
+struct sxe_rst_msg {
+ union {
+ struct sxe_rst_rcv rcv;
+ struct sxe_rst_reply reply;
+ };
+};
+
+struct sxe_ring_info_msg {
+ u32 msg_type;
+ u8 max_rx_num;
+ u8 max_tx_num;
+ u8 tc_num;
+ u8 default_tc;
+};
+
+struct sxe_rss_hash_msg {
+ u32 msg_type;
+ u8 hash_key[SXE_RSS_KEY_SIZE];
+ u64 rss_hf;
+};
+
+struct sxe_vlan_msg {
+ u16 msg_type;
+ u16 add;
+ u32 vlan_id;
+};
+
+struct sxe_mc_sync_msg {
+ u16 msg_type;
+ u16 mc_cnt;
+ u16 mc_addr_extract[SXE_VF_MC_ENTRY_NUM_MAX];
+};
+
+struct sxe_cast_mode_msg {
+ u32 msg_type;
+ u32 cast_mode;
+};
+
+struct sxe_uc_sync_msg {
+ u16 msg_type;
+ u16 index;
+ u32 addr[2];
+};
+
+struct sxe_max_frame_msg {
+ u32 msg_type;
+ u32 max_frame;
+};
+
+s32 sxe_vt_init(struct rte_eth_dev *eth_dev);
+
+void sxe_vt_configure(struct rte_eth_dev *eth_dev);
+
+void sxe_vt_uninit(struct rte_eth_dev *eth_dev);
+
+s32 sxe_vf_rss_configure(struct rte_eth_dev *dev);
+
+s32 sxe_vf_default_mode_configure(struct rte_eth_dev *dev);
+
+void sxe_mbx_irq_handler(struct rte_eth_dev *eth_dev);
+
+#ifdef ETH_DEV_MIRROR_RULE
+s32 sxe_mirror_rule_set(struct rte_eth_dev *dev,
+ struct rte_eth_mirror_conf *mirror_conf,
+ u8 rule_id, u8 on);
+
+s32 sxe_mirror_rule_reset(struct rte_eth_dev *dev, u8 rule_id);
+
+#endif
+#endif
diff --git a/drivers/net/sxe/sxe_testpmd.c b/drivers/net/sxe/sxe_testpmd.c
index 253170df11..b533ae939b 100644
--- a/drivers/net/sxe/sxe_testpmd.c
+++ b/drivers/net/sxe/sxe_testpmd.c
@@ -11,6 +11,131 @@
#include "testpmd.h"
+static int
+vf_tc_min_bw_parse_bw_list(uint8_t *bw_list, uint8_t *tc_num, char *str)
+{
+ uint32_t size;
+ const char *p, *p0 = str;
+ char s[256];
+ char *end;
+ char *str_fld[16];
+ uint16_t i;
+ int ret;
+
+ p = strchr(p0, '(');
+ if (p == NULL) {
+ RTE_LOG_LINE(ERR, EAL, "The bandwidth-list should be '(bw1, bw2, ...)'");
+ return -1;
+ }
+ p++;
+ p0 = strchr(p, ')');
+ if (p0 == NULL) {
+ RTE_LOG_LINE(ERR, EAL, "The bandwidth-list should be '(bw1, bw2, ...)'");
+ return -1;
+ }
+ size = p0 - p;
+ if (size >= sizeof(s)) {
+ RTE_LOG_LINE(ERR, EAL, "The string size exceeds the internal buffer size");
+ return -1;
+ }
+ snprintf(s, sizeof(s), "%.*s", size, p);
+ ret = rte_strsplit(s, sizeof(s), str_fld, 16, ',');
+ if (ret <= 0) {
+ RTE_LOG_LINE(ERR, EAL, "Failed to get the bandwidth list.");
+ return -1;
+ }
+ *tc_num = ret;
+ for (i = 0; i < ret; i++)
+ bw_list[i] = (uint8_t)strtoul(str_fld[i], &end, 0);
+
+ return 0;
+}
+
+struct cmd_vf_tc_bw_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t tc;
+ cmdline_fixed_string_t tx;
+ cmdline_fixed_string_t min_bw;
+ portid_t port_id;
+ cmdline_fixed_string_t bw_list;
+};
+
+static cmdline_parse_token_string_t cmd_vf_tc_bw_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_tc_bw_result,
+ set, "set");
+static cmdline_parse_token_string_t cmd_vf_tc_bw_tc =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_tc_bw_result,
+ tc, "tc");
+static cmdline_parse_token_string_t cmd_vf_tc_bw_tx =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_tc_bw_result,
+ tx, "tx");
+static cmdline_parse_token_string_t cmd_vf_tc_bw_min_bw =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_tc_bw_result,
+ min_bw, "min-bandwidth");
+static cmdline_parse_token_num_t cmd_vf_tc_bw_port_id =
+ TOKEN_NUM_INITIALIZER(struct cmd_vf_tc_bw_result,
+ port_id, RTE_UINT16);
+static cmdline_parse_token_string_t cmd_vf_tc_bw_bw_list =
+ TOKEN_STRING_INITIALIZER(struct cmd_vf_tc_bw_result,
+ bw_list, NULL);
+
+static void
+cmd_tc_min_bw_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl, __rte_unused void *data)
+{
+ struct cmd_vf_tc_bw_result *res = parsed_result;
+ struct rte_port *port;
+ uint8_t tc_num;
+ uint8_t bw[16];
+ int ret = -ENOTSUP;
+
+ if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+ return;
+
+ port = &ports[res->port_id];
+ if (port->port_status != RTE_PORT_STOPPED) {
+ RTE_LOG_LINE(ERR, EAL, "Please stop port %d first", res->port_id);
+ return;
+ }
+
+ ret = vf_tc_min_bw_parse_bw_list(bw, &tc_num, res->bw_list);
+ if (ret)
+ return;
+
+ ret = rte_pmd_sxe_tc_bw_set(res->port_id, tc_num, bw);
+
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ RTE_LOG_LINE(ERR, EAL, "invalid bandwidth");
+ break;
+ case -ENODEV:
+ RTE_LOG_LINE(ERR, EAL, "invalid port_id %d", res->port_id);
+ break;
+ case -ENOTSUP:
+ RTE_LOG_LINE(ERR, EAL, "function not implemented");
+ break;
+ default:
+ RTE_LOG_LINE(ERR, EAL, "programming error: (%s)", strerror(-ret));
+ }
+}
+
+static cmdline_parse_inst_t cmd_tc_min_bw = {
+ .f = cmd_tc_min_bw_parsed,
+ .data = NULL,
+ .help_str = "set tc tx min-bandwidth <port_id> <bw1, bw2, ...>",
+ .tokens = {
+ (void *)&cmd_vf_tc_bw_set,
+ (void *)&cmd_vf_tc_bw_tc,
+ (void *)&cmd_vf_tc_bw_tx,
+ (void *)&cmd_vf_tc_bw_min_bw,
+ (void *)&cmd_vf_tc_bw_port_id,
+ (void *)&cmd_vf_tc_bw_bw_list,
+ NULL,
+ },
+};
+
struct led_ctrl_result {
cmdline_fixed_string_t port;
uint16_t port_id;
@@ -54,6 +179,11 @@ cmdline_parse_inst_t cmd_led_ctrl = {
static struct testpmd_driver_commands sxe_cmds = {
.commands = {
+ {
+ &cmd_tc_min_bw,
+ "set tc tx min-bandwidth (port_id) (bw1, bw2, ...)\n"
+ " Set all TCs' min bandwidth(%%) for all PF and VFs.\n",
+ },
{
&cmd_led_ctrl,
"port <port_id> led on|off\n"
diff --git a/drivers/net/sxe/vf/sxevf.h b/drivers/net/sxe/vf/sxevf.h
new file mode 100644
index 0000000000..b9074d993e
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+#ifndef __SXEVF_H__
+#define __SXEVF_H__
+
+#include <rte_pci.h>
+
+#include "sxevf_irq.h"
+#include "sxevf_hw.h"
+#include "sxevf_filter.h"
+#include "sxevf_stats.h"
+
+#define SXEVF_DEVARG_LINK_CHECK "link_check"
+
+struct sxevf_adapter {
+ s8 name[PCI_PRI_STR_SIZE + 1];
+ u8 max_rx_queue;
+ u8 max_tx_queue;
+
+ struct sxevf_hw hw;
+ struct sxevf_irq_context irq_ctxt;
+ struct sxevf_vlan_context vlan_ctxt;
+ struct sxevf_mac_filter_context mac_filter_ctxt;
+ struct sxevf_stats_info stats_info;
+
+ pthread_t link_thread_tid;
+ u8 link_check;
+ bool stop;
+ bool rx_batch_alloc_allowed;
+#if defined SXE_DPDK_L4_FEATURES && defined SXE_DPDK_SIMD
+ bool rx_vec_allowed;
+#endif
+ u8 rss_reta_updated;
+};
+
+struct sxevf_thread_param {
+ struct rte_eth_dev *dev;
+ pthread_barrier_t barrier;
+};
+
+#endif
+
diff --git a/drivers/net/sxe/vf/sxevf_ethdev.c b/drivers/net/sxe/vf/sxevf_ethdev.c
new file mode 100644
index 0000000000..1466465fe1
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_ethdev.c
@@ -0,0 +1,768 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#if defined SXE_DPDK_L4_FEATURES && defined SXE_DPDK_SRIOV
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <inttypes.h>
+#include "sxe_dpdk_version.h"
+#include <ethdev_driver.h>
+#include <ethdev_pci.h>
+#include <bus_pci_driver.h>
+
+#include <rte_ethdev.h>
+#include <rte_kvargs.h>
+#include <rte_common.h>
+#include <rte_string_fns.h>
+
+#include "sxevf.h"
+#include "sxe_rx.h"
+#include "sxe_logs.h"
+#include "sxevf_msg.h"
+#include "sxe_errno.h"
+#include "sxevf_tx.h"
+#include "sxevf_rx.h"
+#include "sxevf_ethdev.h"
+#include "sxevf_queue.h"
+#include "sxevf_offload.h"
+#include "sxe_compat_version.h"
+
+#define SXEVF_ETH_OVERHEAD (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN)
+#define SXEVF_HKEY_MAX_INDEX (10)
+#define SXEVF_RSS_OFFLOAD_ALL ( \
+ RTE_ETH_RSS_IPV4 | \
+ RTE_ETH_RSS_NONFRAG_IPV4_TCP | \
+ RTE_ETH_RSS_NONFRAG_IPV4_UDP | \
+ RTE_ETH_RSS_IPV6 | \
+ RTE_ETH_RSS_NONFRAG_IPV6_TCP | \
+ RTE_ETH_RSS_NONFRAG_IPV6_UDP | \
+ RTE_ETH_RSS_IPV6_EX | \
+ RTE_ETH_RSS_IPV6_TCP_EX | \
+ RTE_ETH_RSS_IPV6_UDP_EX)
+
+#define SXEVF_DEFAULT_RX_FREE_THRESH 32
+#define SXEVF_DEFAULT_RX_PTHRESH 8
+#define SXEVF_DEFAULT_RX_HTHRESH 8
+#define SXEVF_DEFAULT_RX_WTHRESH 0
+
+#define SXEVF_DEFAULT_TX_FREE_THRESH 32
+#define SXEVF_DEFAULT_TX_PTHRESH 32
+#define SXEVF_DEFAULT_TX_HTHRESH 0
+#define SXEVF_DEFAULT_TX_WTHRESH 0
+#define SXEVF_DEFAULT_TX_RSBIT_THRESH 32
+
+#define SXEVF_MIN_RING_DESC 32
+#define SXEVF_MAX_RING_DESC 4096
+
+#define SXEVF_ALIGN 128
+#define SXEVF_RXD_ALIGN (SXEVF_ALIGN / sizeof(sxevf_rx_data_desc_u))
+#define SXEVF_TXD_ALIGN (SXEVF_ALIGN / sizeof(sxevf_tx_data_desc_u))
+
+#define SXEVF_TX_MAX_SEG 40
+#define SXEVF_DEFAULT_TX_QUEUE_NUM 1
+#define SXEVF_DEFAULT_RX_QUEUE_NUM 1
+#define SXEVF_RX_BUF_MIN 1024
+#define SXEVF_RX_BUF_LEN_MAX 9728
+
+static const struct rte_eth_desc_lim rx_desc_lim = {
+ .nb_max = SXEVF_MAX_RING_DESC,
+ .nb_min = SXEVF_MIN_RING_DESC,
+ .nb_align = SXEVF_RXD_ALIGN,
+};
+
+static const struct rte_eth_desc_lim tx_desc_lim = {
+ .nb_max = SXEVF_MAX_RING_DESC,
+ .nb_min = SXEVF_MIN_RING_DESC,
+ .nb_align = SXEVF_TXD_ALIGN,
+ .nb_seg_max = SXEVF_TX_MAX_SEG,
+ .nb_mtu_seg_max = SXEVF_TX_MAX_SEG,
+};
+
+static const char * const sxevf_valid_arguments[] = {
+ SXEVF_DEVARG_LINK_CHECK,
+ NULL
+};
+
+static s32 sxevf_devargs_handle(__rte_unused const char *key, const char *value,
+ void *extra_args)
+{
+ u16 *n = extra_args;
+ s32 ret;
+
+ if (value == NULL || extra_args == NULL) {
+ ret = -EINVAL;
+ LOG_ERROR("invalid args.(err:%d)", ret);
+ goto l_out;
+ }
+
+ *n = (u16)strtoul(value, NULL, 0);
+ if (*n == USHRT_MAX && errno == ERANGE) {
+ ret = -ERANGE;
+ LOG_ERROR("invalid args.(err:%d)", ret);
+ goto l_out;
+ }
+
+ ret = 0;
+
+l_out:
+ return ret;
+}
+
+static void sxevf_devargs_parse(struct sxevf_adapter *adapter,
+ struct rte_devargs *devargs)
+{
+ struct rte_kvargs *kvlist;
+ u16 check;
+
+ if (devargs == NULL) {
+ LOG_INFO_BDF("no dev args.");
+ return;
+ }
+
+ kvlist = rte_kvargs_parse(devargs->args, sxevf_valid_arguments);
+ if (kvlist == NULL)
+ return;
+
+ if (rte_kvargs_count(kvlist, SXEVF_DEVARG_LINK_CHECK) == 1 &&
+ rte_kvargs_process(kvlist, SXEVF_DEVARG_LINK_CHECK,
+ sxevf_devargs_handle, &check) == 0 &&
+ check == 1) {
+ adapter->link_check = 1;
+ }
+
+ LOG_INFO_BDF("dev args link_check:%u", adapter->link_check);
+
+ rte_kvargs_free(kvlist);
+}
+
+static s32 sxevf_hw_dev_reset(struct sxevf_hw *hw)
+{
+ u32 retry = SXEVF_RST_CHECK_NUM;
+ s32 ret;
+ struct sxevf_rst_msg msg = {};
+ struct sxevf_adapter *adapter = hw->adapter;
+ u8 *mac_addr = adapter->mac_filter_ctxt.def_mac_addr.addr_bytes;
+
+ UNUSED(mac_addr);
+ adapter->stop = true;
+
+ sxevf_hw_stop(hw);
+
+ /* Mail box init */
+ sxevf_mbx_init(hw);
+
+
+ sxevf_hw_reset(hw);
+
+ while (!sxevf_pf_rst_check(hw) && retry) {
+ retry--;
+ sxe_udelay(5);
+ }
+
+ if (!retry) {
+ ret = -SXEVF_ERR_RESET_FAILED;
+ LOG_ERROR_BDF("retry: %u use up, pf has not reset done.(err:%d)",
+ SXEVF_RST_CHECK_NUM, ret);
+ goto l_out;
+ }
+
+ LOG_INFO_BDF("pf reset done.");
+
+ hw->mbx.retry = SXEVF_MBX_RETRY_COUNT;
+
+ sxevf_rxtx_reg_init(hw);
+
+ /* Send reset message to pf */
+ msg.msg_type = SXEVF_RESET;
+ ret = sxevf_send_and_rcv_msg(hw, (u32 *)&msg,
+ SXEVF_MSG_NUM(sizeof(msg)));
+ if (ret) {
+ LOG_ERROR_BDF("vf reset msg:%d len:%zu mailbox fail.(err:%d)",
+ msg.msg_type, SXEVF_MSG_NUM(sizeof(msg)), ret);
+ goto l_out;
+ }
+
+ if (msg.msg_type == (SXEVF_RESET | SXEVF_MSGTYPE_ACK)) {
+ memcpy(&adapter->mac_filter_ctxt.def_mac_addr,
+ (u8 *)(msg.mac_addr), SXEVF_MAC_ADDR_LEN);
+ }
+
+ adapter->mac_filter_ctxt.mc_filter_type = msg.mc_fiter_type;
+
+ LOG_INFO_BDF("vf get mc filter type:%d default mac addr:" RTE_ETHER_ADDR_PRT_FMT " from pf.",
+ adapter->mac_filter_ctxt.mc_filter_type,
+ mac_addr[0], mac_addr[1], mac_addr[2],
+ mac_addr[3], mac_addr[4], mac_addr[5]);
+
+l_out:
+ return ret;
+}
+
+static s32 sxevf_hw_base_init(struct rte_eth_dev *eth_dev)
+{
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ s32 ret;
+
+ hw->reg_base_addr = (void *)pci_dev->mem_resource[0].addr;
+ PMD_LOG_INFO(INIT, "eth_dev[%u] got reg_base_addr=%p",
+ eth_dev->data->port_id, hw->reg_base_addr);
+ hw->adapter = adapter;
+
+ strlcpy(adapter->name, pci_dev->device.name, sizeof(adapter->name) - 1);
+ adapter->stop = true;
+
+ adapter->max_rx_queue = SXEVF_DEFAULT_RX_QUEUE_NUM;
+ adapter->max_tx_queue = SXEVF_DEFAULT_TX_QUEUE_NUM;
+
+ ret = sxevf_hw_dev_reset(hw);
+ if (ret < 0) {
+ PMD_LOG_ERR(INIT, "hw dev reset failed, ret=%d", ret);
+ goto l_out;
+ } else {
+ adapter->stop = false;
+ }
+
+ ret = sxevf_mac_addr_init(eth_dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "mac addr init fail, ret=%d", ret);
+ goto l_out;
+ }
+
+l_out:
+ return ret;
+}
+
+static void sxevf_txrx_start(struct rte_eth_dev *eth_dev)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ sxevf_tx_queue_s *txq;
+ sxevf_rx_queue_s *rxq;
+ u16 i;
+
+ for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
+ txq = eth_dev->data->tx_queues[i];
+ sxevf_tx_ring_switch(hw, txq->reg_idx, true);
+ eth_dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
+ }
+
+ for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
+ rxq = eth_dev->data->rx_queues[i];
+ sxevf_rx_ring_switch(hw, rxq->reg_idx, true);
+ eth_dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
+ rte_wmb();
+
+ sxevf_rx_desc_tail_set(hw, rxq->reg_idx, rxq->ring_depth - 1);
+ }
+}
+
+static s32 sxevf_dev_start(struct rte_eth_dev *dev)
+{
+ s32 ret;
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_stats_info *stats_info = &adapter->stats_info;
+ struct sxevf_hw *hw = &adapter->hw;
+
+ PMD_INIT_FUNC_TRACE();
+
+ ret = sxevf_hw_dev_reset(hw);
+ if (ret) {
+ LOG_ERROR_BDF("dev reset fail.");
+ goto l_out;
+ }
+
+ sxevf_mbx_api_version_init(adapter);
+
+ sxevf_tx_configure(dev);
+
+ ret = sxevf_rx_configure(dev);
+ if (ret) {
+ LOG_ERROR_BDF("rx configure fail.(err:%d)", ret);
+ goto l_clear_queue;
+ }
+
+ sxevf_vlan_filter_configure(dev);
+
+ sxevf_txrx_start(dev);
+
+ sxevf_irq_configure(dev);
+
+ sxevf_stats_init_value_get(hw, &stats_info->hw_stats);
+
+ adapter->stop = false;
+
+l_out:
+ return ret;
+
+l_clear_queue:
+ sxevf_txrx_queues_clear(dev, adapter->rx_batch_alloc_allowed);
+ return ret;
+}
+
+static s32 sxevf_dev_stop(struct rte_eth_dev *dev)
+{
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+
+ PMD_INIT_FUNC_TRACE();
+
+ if (adapter->stop) {
+ LOG_INFO_BDF("eth dev has been stopped.");
+ goto l_out;
+ }
+
+ adapter->stop = false;
+ dev->data->dev_started = false;
+ dev->data->scattered_rx = false;
+
+ sxevf_hw_stop(hw);
+
+ sxevf_vfta_sync(dev, false);
+
+ sxevf_txrx_queues_clear(dev, adapter->rx_batch_alloc_allowed);
+
+ sxevf_irq_free(dev);
+
+l_out:
+
+ return 0;
+}
+
+static s32 sxevf_dev_close(struct rte_eth_dev *dev)
+{
+ s32 ret = 0;
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_stats_info *stats_info = &adapter->stats_info;
+ struct sxevf_hw *hw = &adapter->hw;
+
+ PMD_INIT_FUNC_TRACE();
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+ LOG_INFO_BDF("secondery procee can't close dev.");
+ goto l_out;
+ }
+
+ ret = sxevf_hw_dev_reset(hw);
+ if (ret)
+ LOG_ERROR_BDF("dev reset fail.");
+
+ sxevf_dev_stop(dev);
+
+ sxevf_stats_init_value_get(hw, &stats_info->hw_stats);
+
+ sxevf_queues_free(dev);
+
+ sxevf_irq_unregister(dev);
+
+l_out:
+
+ return ret;
+}
+
+static s32 sxevf_dev_reset(struct rte_eth_dev *dev)
+{
+ s32 ret;
+
+ ret = sxevf_ethdev_uninit(dev);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "dev uninit fail.");
+ goto l_out;
+ }
+
+ ret = sxevf_ethdev_init(dev);
+ if (ret)
+ PMD_LOG_ERR(INIT, "dev init fail.");
+
+l_out:
+ return ret;
+}
+
+static s32 sxevf_dev_info_get(struct rte_eth_dev *dev,
+ struct rte_eth_dev_info *dev_info)
+{
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+
+ dev_info->max_rx_queues = adapter->max_rx_queue;
+ dev_info->max_tx_queues = adapter->max_tx_queue;
+ dev_info->min_rx_bufsize = SXEVF_RX_BUF_MIN;
+ dev_info->max_rx_pktlen = SXEVF_RX_BUF_LEN_MAX;
+ dev_info->max_mtu = dev_info->max_rx_pktlen - SXEVF_ETH_OVERHEAD;
+ dev_info->max_mac_addrs = adapter->mac_filter_ctxt.uc_table_size;
+ dev_info->max_hash_mac_addrs = SXEVF_UTA_HASH_BIT_MAX;
+ dev_info->max_vfs = pci_dev->max_vfs;
+ dev_info->max_vmdq_pools = RTE_ETH_64_POOLS;
+
+ dev_info->rx_queue_offload_capa = sxevf_rx_queue_offloads_get(dev);
+ dev_info->rx_offload_capa = (sxevf_rx_port_offloads_get(dev) |
+ dev_info->rx_queue_offload_capa);
+ dev_info->tx_queue_offload_capa = sxevf_tx_queue_offloads_get(dev);
+ dev_info->tx_offload_capa = sxevf_tx_port_offloads_get(dev);
+
+ dev_info->hash_key_size = SXEVF_HKEY_MAX_INDEX * sizeof(u32);
+ dev_info->reta_size = 0;
+ dev_info->flow_type_rss_offloads = SXEVF_RSS_OFFLOAD_ALL;
+
+ dev_info->default_rxconf = (struct rte_eth_rxconf) {
+ .rx_thresh = {
+ .pthresh = SXEVF_DEFAULT_RX_PTHRESH,
+ .hthresh = SXEVF_DEFAULT_RX_HTHRESH,
+ .wthresh = SXEVF_DEFAULT_RX_WTHRESH,
+ },
+ .rx_free_thresh = SXEVF_DEFAULT_RX_FREE_THRESH,
+ .rx_drop_en = 0,
+ .offloads = 0,
+ };
+
+ dev_info->default_txconf = (struct rte_eth_txconf) {
+ .tx_thresh = {
+ .pthresh = SXEVF_DEFAULT_TX_PTHRESH,
+ .hthresh = SXEVF_DEFAULT_TX_HTHRESH,
+ .wthresh = SXEVF_DEFAULT_TX_WTHRESH,
+ },
+ .tx_free_thresh = SXEVF_DEFAULT_TX_FREE_THRESH,
+ .tx_rs_thresh = SXEVF_DEFAULT_TX_RSBIT_THRESH,
+ .offloads = 0,
+ };
+
+ dev_info->rx_desc_lim = rx_desc_lim;
+ dev_info->tx_desc_lim = tx_desc_lim;
+
+ dev_info->err_handle_mode = RTE_ETH_ERROR_HANDLE_MODE_PASSIVE;
+
+ return 0;
+}
+
+static s32 sxevf_mtu_set(struct rte_eth_dev *dev, u16 mtu)
+{
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ u32 max_frame = mtu + SXEVF_ETH_OVERHEAD;
+ s32 ret;
+
+ if (mtu < RTE_ETHER_MIN_MTU ||
+ max_frame > RTE_ETHER_MAX_JUMBO_FRAME_LEN) {
+ ret = -EINVAL;
+ LOG_ERROR_BDF("invalid mtu:%u.", mtu);
+ goto l_out;
+ }
+
+ if (dev->data->dev_started && !dev->data->scattered_rx &&
+ ((max_frame + 2 * SXEVF_VLAN_TAG_SIZE) >
+ (dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM))) {
+ ret = -EINVAL;
+ LOG_ERROR_BDF("max_frame:%u stop port first.(err:%d)",
+ max_frame, ret);
+ goto l_out;
+ }
+
+ ret = sxevf_rx_max_frame_set(hw, mtu);
+ if (ret) {
+ LOG_ERROR_BDF("max_frame:%u set fail.(err:%d)", max_frame, ret);
+ ret = -EINVAL;
+ goto l_out;
+ }
+
+ dev->data->dev_conf.rxmode.max_rx_pkt_len = max_frame;
+ LOG_INFO_BDF("change max frame size to %u success.", max_frame);
+
+l_out:
+ return ret;
+}
+
+static s32 sxevf_dev_configure(struct rte_eth_dev *dev)
+{
+ struct rte_eth_conf *conf = &dev->data->dev_conf;
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+
+ LOG_INFO_BDF("Configured Virtual Function port id: %d",
+ dev->data->port_id);
+
+ if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)
+ dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
+
+#ifndef RTE_LIBRTE_SXEVF_PF_DISABLE_STRIP_CRC
+ if (conf->rxmode.offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC) {
+ LOG_INFO_BDF("VF can't disable HW CRC Strip");
+ conf->rxmode.offloads &= ~RTE_ETH_RX_OFFLOAD_KEEP_CRC;
+ }
+#else
+ if (!(conf->rxmode.offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC)) {
+ LOG_INFO_BDF("VF can't enable HW CRC Strip");
+ conf->rxmode.offloads |= RTE_ETH_RX_OFFLOAD_KEEP_CRC;
+ }
+#endif
+
+ adapter->rx_batch_alloc_allowed = true;
+
+#if defined SXE_DPDK_L4_FEATURES && defined SXE_DPDK_SIMD
+ adapter->rx_vec_allowed = true;
+#endif
+
+ return 0;
+}
+
+static const struct sxevf_reg_info sxevf_regs_general[] = {
+ {SXE_VFCTRL, 1, 1, "SXE_VFCTRL"},
+ {SXE_VFSTATUS, 1, 1, "SXE_VFSTATUS"},
+ {SXE_VFLINKS, 1, 1, "SXE_VFLINKS"},
+ {SXE_VFFRTIMER, 1, 1, "SXE_VFFRTIMER"},
+ {SXE_VFMAILBOX, 1, 1, "SXE_VFMAILBOX"},
+ {SXE_VFMBMEM, 16, 4, "SXE_VFMBMEM"},
+ {SXE_VFRXMEMWRAP, 1, 1, "SXE_VFRXMEMWRAP"},
+ {0, 0, 0, ""}
+};
+
+static const struct sxevf_reg_info sxevf_regs_interrupt[] = {
+ {SXE_VFEICR, 1, 1, "SXE_VFEICR"},
+ {SXE_VFEICS, 1, 1, "SXE_VFEICS"},
+ {SXE_VFEIMS, 1, 1, "SXE_VFEIMS"},
+ {SXE_VFEIMC, 1, 1, "SXE_VFEIMC"},
+ {SXE_VFEIAM, 1, 1, "SXE_VFEIAM"},
+ {SXE_VFEITR(0), 2, 4, "SXE_VFEITR"},
+ {SXE_VFIVAR(0), 4, 4, "SXE_VFIVAR"},
+ {SXE_VFIVAR_MISC, 1, 1, "SXE_VFIVAR_MISC"},
+ {0, 0, 0, ""}
+};
+
+static const struct sxevf_reg_info sxevf_regs_rxdma[] = {
+ {SXE_VFRDBAL(0), 8, 0x40, "SXE_VFRDBAL"},
+ {SXE_VFRDBAH(0), 8, 0x40, "SXE_VFRDBAH"},
+ {SXE_VFRDLEN(0), 8, 0x40, "SXE_VFRDLEN"},
+ {SXE_VFRDH(0), 8, 0x40, "SXE_VFRDH"},
+ {SXE_VFRDT(0), 8, 0x40, "SXE_VFRDT"},
+ {SXE_VFRXDCTL(0), 8, 0x40, "SXE_VFRXDCTL"},
+ {SXE_VFSRRCTL(0), 8, 0x40, "SXE_VFSRRCTL"},
+ {SXE_VFPSRTYPE, 1, 1, "SXE_VFPSRTYPE"},
+ {SXE_VFLROCTL(0), 8, 0x40, "SXE_VFRSCCTL"},
+ {SXE_VFDCA_RXCTRL(0), 8, 0x40, "SXE_VFDCA_RXCTRL"},
+ {SXE_VFDCA_TXCTRL(0), 8, 0x40, "SXE_VFDCA_TXCTRL"},
+ {0, 0, 0, ""}
+};
+
+static const struct sxevf_reg_info sxevf_regs_tx[] = {
+ {SXE_VFTDBAL(0), 4, 0x40, "SXE_VFTDBAL"},
+ {SXE_VFTDBAH(0), 4, 0x40, "SXE_VFTDBAH"},
+ {SXE_VFTDLEN(0), 4, 0x40, "SXE_VFTDLEN"},
+ {SXE_VFTDH(0), 4, 0x40, "SXE_VFTDH"},
+ {SXE_VFTDT(0), 4, 0x40, "SXE_VFTDT"},
+ {SXE_VFTXDCTL(0), 4, 0x40, "SXE_VFTXDCTL"},
+ {SXE_VFTDWBAL(0), 4, 0x40, "SXE_VFTDWBAL"},
+ {SXE_VFTDWBAH(0), 4, 0x40, "SXE_VFTDWBAH"},
+ {0, 0, 0, ""}
+};
+
+static const struct sxevf_reg_info *sxevf_regs_group[] = {
+ sxevf_regs_general,
+ sxevf_regs_interrupt,
+ sxevf_regs_rxdma,
+ sxevf_regs_tx,
+ NULL};
+
+static u32 sxevf_regs_group_count(const struct sxevf_reg_info *regs)
+{
+ int i = 0;
+ int count = 0;
+
+ while (regs[i].count)
+ count += regs[i++].count;
+
+ return count;
+};
+
+u32 sxevf_regs_group_num_get(void)
+{
+ u32 i = 0;
+ u32 count = 0;
+ const struct sxevf_reg_info *reg_group;
+ const struct sxevf_reg_info **reg_set = sxevf_regs_group;
+
+ while ((reg_group = reg_set[i++]))
+ count += sxevf_regs_group_count(reg_group);
+
+ PMD_LOG_INFO(INIT, "read regs cnt=%u", count);
+
+ return count;
+}
+
+void sxevf_regs_group_read(struct sxevf_hw *hw, u32 *data)
+{
+ u32 cnt = 0, i = 0;
+ const struct sxevf_reg_info *reg_group;
+ const struct sxevf_reg_info **reg_set = sxevf_regs_group;
+
+ while ((reg_group = reg_set[i++]))
+ cnt += sxevf_hw_regs_group_read(hw, reg_group, &data[cnt]);
+
+ PMD_LOG_INFO(INIT, "read regs cnt=%u, regs num=%u",
+ cnt, sxevf_regs_group_num_get());
+}
+
+static int sxevf_get_regs(struct rte_eth_dev *dev,
+ struct rte_dev_reg_info *regs)
+{
+ s32 ret = 0;
+ u32 *data = regs->data;
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ u32 length = sxevf_regs_group_num_get();
+
+ if (data == NULL) {
+ regs->length = length;
+ regs->width = sizeof(u32);
+ goto l_end;
+ }
+
+ if (regs->length == 0 || regs->length == length) {
+ sxevf_regs_group_read(hw, data);
+
+ goto l_end;
+ }
+
+ ret = -ENOTSUP;
+ PMD_LOG_ERR(INIT, "get regs: inval param: regs_len=%u, regs->data=%p, "
+ "regs_offset=%u, regs_width=%u, regs_version=%u",
+ regs->length, regs->data,
+ regs->offset, regs->width,
+ regs->version);
+
+l_end:
+ return ret;
+}
+
+static const struct eth_dev_ops sxevf_eth_dev_ops = {
+ .dev_configure = sxevf_dev_configure,
+ .dev_start = sxevf_dev_start,
+ .dev_stop = sxevf_dev_stop,
+ .link_update = sxevf_link_update,
+ .stats_get = sxevf_eth_stats_get,
+ .xstats_get = sxevf_xstats_get,
+ .stats_reset = sxevf_dev_stats_reset,
+ .xstats_reset = sxevf_dev_stats_reset,
+ .xstats_get_names = sxevf_xstats_names_get,
+ .dev_close = sxevf_dev_close,
+ .dev_reset = sxevf_dev_reset,
+ .promiscuous_enable = sxevf_promiscuous_enable,
+ .promiscuous_disable = sxevf_promiscuous_disable,
+ .allmulticast_enable = sxevf_allmulticast_enable,
+ .allmulticast_disable = sxevf_allmulticast_disable,
+ .dev_infos_get = sxevf_dev_info_get,
+ .dev_supported_ptypes_get = sxevf_dev_supported_ptypes_get,
+ .mtu_set = sxevf_mtu_set,
+ .vlan_filter_set = sxevf_vlan_filter_set,
+ .vlan_strip_queue_set = sxevf_vlan_strip_queue_set,
+ .vlan_offload_set = sxevf_vlan_offload_set,
+ .rx_queue_setup = sxevf_rx_queue_setup,
+ .rx_queue_release = sxevf_rx_queue_release,
+ .tx_queue_setup = sxevf_tx_queue_setup,
+ .tx_queue_release = sxevf_tx_queue_release,
+ .rx_queue_intr_enable = sxevf_rx_queue_intr_enable,
+ .rx_queue_intr_disable = sxevf_rx_queue_intr_disable,
+ .mac_addr_add = sxevf_mac_addr_add,
+ .mac_addr_remove = sxevf_mac_addr_remove,
+ .set_mc_addr_list = sxevf_set_mc_addr_list,
+ .rxq_info_get = sxevf_rx_queue_info_get,
+ .txq_info_get = sxevf_tx_queue_info_get,
+ .mac_addr_set = sxevf_default_mac_addr_set,
+ .get_reg = sxevf_get_regs,
+ .reta_update = sxevf_rss_reta_update,
+ .reta_query = sxevf_rss_reta_query,
+ .rss_hash_update = sxevf_rss_hash_update,
+ .rss_hash_conf_get = sxevf_rss_hash_conf_get,
+ .tx_done_cleanup = sxevf_tx_done_cleanup,
+#ifdef ETH_DEV_OPS_MONITOR
+ .get_monitor_addr = sxe_monitor_addr_get,
+#endif
+#ifdef ETH_DEV_OPS_HAS_DESC_RELATE
+ .rx_descriptor_status = sxevf_rx_descriptor_status,
+ .tx_descriptor_status = sxevf_tx_descriptor_status,
+#ifdef ETH_DEV_RX_DESC_DONE
+ .rx_descriptor_done = sxevf_rx_descriptor_done,
+#endif
+#endif
+};
+
+s32 sxevf_ethdev_init(struct rte_eth_dev *eth_dev)
+{
+ s32 ret = 0;
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_stats_info *stats_info = &adapter->stats_info;
+ struct sxevf_hw *hw = &adapter->hw;
+ u8 default_tc;
+ u8 tc_num;
+
+ PMD_INIT_FUNC_TRACE();
+
+ eth_dev->dev_ops = &sxevf_eth_dev_ops;
+
+#ifndef ETH_DEV_OPS_HAS_DESC_RELATE
+ eth_dev->rx_descriptor_status = sxevf_rx_descriptor_status;
+ eth_dev->tx_descriptor_status = sxevf_tx_descriptor_status;
+#ifdef ETH_DEV_RX_DESC_DONE
+ eth_dev->rx_descriptor_done = sxevf_rx_descriptor_done;
+#endif
+#endif
+
+ eth_dev->rx_pkt_burst = &sxevf_pkts_recv;
+ eth_dev->tx_pkt_burst = &sxevf_pkts_xmit_with_offload;
+
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+ sxevf_secondary_proc_init(eth_dev);
+ goto l_out;
+ }
+
+ sxevf_devargs_parse(eth_dev->data->dev_private,
+ pci_dev->device.devargs);
+
+ rte_eth_copy_pci_info(eth_dev, pci_dev);
+
+ eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
+
+ ret = sxevf_hw_base_init(eth_dev);
+ if (ret) {
+ ret = -EIO;
+ LOG_ERROR_BDF("hw base init fail.(err:%d)", ret);
+ goto l_out;
+ }
+
+ sxevf_dev_stats_reset(eth_dev);
+
+ sxevf_stats_init_value_get(hw, &stats_info->hw_stats);
+
+ sxevf_mbx_api_version_init(adapter);
+
+ sxevf_ring_info_get(adapter, &default_tc, &tc_num);
+
+ sxevf_irq_init(eth_dev);
+
+ LOG_INFO_BDF("sxevf eth dev init done.");
+
+l_out:
+ return ret;
+}
+
+s32 sxevf_ethdev_uninit(struct rte_eth_dev *eth_dev)
+{
+ s32 ret = 0;
+
+ PMD_INIT_FUNC_TRACE();
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+ PMD_LOG_WARN(INIT, "secondery procee can't unint.");
+ goto l_out;
+ }
+
+ sxevf_dev_close(eth_dev);
+
+l_out:
+ return ret;
+}
+
+#endif
diff --git a/drivers/net/sxe/vf/sxevf_ethdev.h b/drivers/net/sxe/vf/sxevf_ethdev.h
new file mode 100644
index 0000000000..57dfeea2e6
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_ethdev.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#ifndef __SXEVF_ETHDEV_H__
+#define __SXEVF_ETHDEV_H__
+
+s32 sxevf_ethdev_init(struct rte_eth_dev *eth_dev);
+
+s32 sxevf_ethdev_uninit(struct rte_eth_dev *eth_dev);
+
+u32 sxevf_regs_group_num_get(void);
+
+void sxevf_regs_group_read(struct sxevf_hw *hw, u32 *data);
+
+#endif
diff --git a/drivers/net/sxe/vf/sxevf_filter.c b/drivers/net/sxe/vf/sxevf_filter.c
new file mode 100644
index 0000000000..c4875f82bc
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_filter.c
@@ -0,0 +1,493 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#if defined SXE_DPDK_L4_FEATURES && defined SXE_DPDK_SRIOV
+
+#include <string.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+
+#include "sxevf.h"
+#include "sxe_logs.h"
+#include "sxevf_msg.h"
+#include "sxe_errno.h"
+#include "sxevf_filter.h"
+#include "sxevf_rx.h"
+#include "sxevf_queue.h"
+#include "sxe_compat_version.h"
+
+#define SXEVF_MAC_ADDR_EXTRACT_MASK (0xFFF)
+#define SXEVF_MAC_ADDR_SHIFT (5)
+#define SXEVF_MAC_ADDR_REG_MASK (0x7F)
+#define SXEVF_MAC_ADDR_BIT_MASK (0x1F)
+
+#define SXEVF_STRIP_BITMAP_SET(h, q) \
+ do { \
+ u32 idx = (q) / (sizeof((h)->strip_bitmap[0]) * BYTE_BIT_NUM); \
+ u32 bit = (q) % (sizeof((h)->strip_bitmap[0]) * BYTE_BIT_NUM); \
+ (h)->strip_bitmap[idx] |= 1 << bit;\
+ } while (0)
+
+#define SXEVF_STRIP_BITMAP_CLEAR(h, q) \
+ do {\
+ u32 idx = (q) / (sizeof((h)->strip_bitmap[0]) * BYTE_BIT_NUM); \
+ u32 bit = (q) % (sizeof((h)->strip_bitmap[0]) * BYTE_BIT_NUM); \
+ (h)->strip_bitmap[idx] &= ~(1 << bit);\
+ } while (0)
+
+#define SXEVF_STRIP_BITMAP_GET(h, q, r) \
+ do {\
+ u32 idx = (q) / (sizeof((h)->strip_bitmap[0]) * BYTE_BIT_NUM); \
+ u32 bit = (q) % (sizeof((h)->strip_bitmap[0]) * BYTE_BIT_NUM); \
+ (r) = (h)->strip_bitmap[idx] >> bit & 1;\
+ } while (0)
+
+static void sxevf_random_mac_addr_generate(struct rte_ether_addr *mac_addr)
+{
+ u64 random;
+
+ mac_addr->addr_bytes[0] = 0xe4;
+ mac_addr->addr_bytes[1] = 0xb6;
+ mac_addr->addr_bytes[2] = 0x33;
+
+ mac_addr->addr_bytes[0] |= RTE_ETHER_LOCAL_ADMIN_ADDR;
+
+ random = rte_rand();
+ memcpy(&mac_addr->addr_bytes[3], &random, 3);
+}
+
+s32 sxevf_mac_addr_init(struct rte_eth_dev *eth_dev)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ struct sxevf_mac_filter_context *mac_filter = &adapter->mac_filter_ctxt;
+ s32 ret = 0;
+ u8 *mac_addr;
+
+ UNUSED(mac_addr);
+ eth_dev->data->mac_addrs = rte_zmalloc("sxe",
+ RTE_ETHER_ADDR_LEN * SXEVF_HW_UC_ENTRY_NUM_MAX, 0);
+ if (eth_dev->data->mac_addrs == NULL) {
+ LOG_ERROR_BDF("mac addr allocate %u B fail.",
+ RTE_ETHER_ADDR_LEN * SXEVF_HW_UC_ENTRY_NUM_MAX);
+ ret = -ENOMEM;
+ goto l_out;
+ }
+
+ if (rte_is_zero_ether_addr(&mac_filter->def_mac_addr)) {
+ sxevf_random_mac_addr_generate(&mac_filter->def_mac_addr);
+ ret = sxevf_mac_addr_set(hw, mac_filter->def_mac_addr.addr_bytes);
+ if (ret) {
+ LOG_ERROR_BDF("vf uc mac addr set fail.(err:%d)", ret);
+ goto l_free;
+ }
+ mac_addr = mac_filter->def_mac_addr.addr_bytes;
+ LOG_INFO_BDF("generate random mac_addr:" RTE_ETHER_ADDR_PRT_FMT,
+ mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
+ mac_addr[4], mac_addr[5]);
+ }
+
+ rte_ether_addr_copy(&mac_filter->def_mac_addr, ð_dev->data->mac_addrs[0]);
+
+ mac_filter->uc_table_size = SXEVF_HW_UC_ENTRY_NUM_MAX;
+
+l_out:
+ return ret;
+
+l_free:
+ rte_free(eth_dev->data->mac_addrs);
+ eth_dev->data->mac_addrs = NULL;
+ return ret;
+}
+
+void sxevf_vfta_sync(struct rte_eth_dev *eth_dev, bool on)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ struct sxevf_vlan_context *vlan_ctxt = &adapter->vlan_ctxt;
+ u32 reg_idx;
+ u32 bit_idx;
+ u32 vfta;
+ u32 mask;
+ u32 vlan_id;
+
+ for (reg_idx = 0; reg_idx < SXEVF_VFT_TBL_SIZE; reg_idx++) {
+ vfta = vlan_ctxt->vlan_table[reg_idx];
+ if (vfta) {
+ mask = 1;
+ for (bit_idx = 0; bit_idx < 32; bit_idx++) {
+ vlan_id = (reg_idx << 5) + bit_idx;
+ if (vfta & mask)
+ sxevf_vlan_id_set(hw, vlan_id, on);
+ mask <<= 1;
+ }
+ }
+ }
+}
+
+static void sxevf_vlan_strip_bitmap_set(struct rte_eth_dev *dev, u16 queue_idx, bool on)
+{
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_vlan_context *vlan_ctxt = &adapter->vlan_ctxt;
+ sxevf_rx_queue_s *rxq;
+
+ if (queue_idx >= adapter->max_rx_queue) {
+ LOG_ERROR_BDF("invalid queue idx:%u exceed max"
+ " queue number:%u.",
+ queue_idx, adapter->max_rx_queue);
+ return;
+ }
+
+ if (on)
+ SXEVF_STRIP_BITMAP_SET(vlan_ctxt, queue_idx);
+ else
+ SXEVF_STRIP_BITMAP_CLEAR(vlan_ctxt, queue_idx);
+
+ if (queue_idx >= dev->data->nb_rx_queues) {
+ LOG_ERROR_BDF("invalid queue_idx id:%u exceed rx "
+ " queue number:%u.",
+ queue_idx, dev->data->nb_rx_queues);
+ return;
+ }
+
+ rxq = dev->data->rx_queues[queue_idx];
+
+ if (on) {
+ rxq->vlan_flags = RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
+ rxq->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
+ } else {
+ rxq->vlan_flags = RTE_MBUF_F_RX_VLAN;
+ rxq->offloads &= ~RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
+ }
+
+ LOG_INFO_BDF("queue idx:%u vlan strip on:%d set bitmap and offload done.",
+ queue_idx, on);
+}
+
+static void sxevf_vlan_strip_switch_set(struct rte_eth_dev *dev)
+{
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ u16 i;
+ sxevf_rx_queue_s *rxq;
+ bool on;
+
+ PMD_INIT_FUNC_TRACE();
+
+ for (i = 0; i < dev->data->nb_rx_queues; i++) {
+ rxq = dev->data->rx_queues[i];
+
+ if (rxq->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
+ on = true;
+ else
+ on = false;
+
+ sxevf_hw_vlan_tag_strip_switch(hw, i, on);
+
+ sxevf_vlan_strip_bitmap_set(dev, i, on);
+ }
+}
+
+static void sxevf_vlan_offload_configure(struct rte_eth_dev *dev, s32 mask)
+{
+ if (mask & RTE_ETH_VLAN_STRIP_MASK)
+ sxevf_vlan_strip_switch_set(dev);
+}
+
+void sxevf_vlan_filter_configure(struct rte_eth_dev *eth_dev)
+{
+ u32 vlan_mask;
+
+ sxevf_vfta_sync(eth_dev, true);
+
+ vlan_mask = RTE_ETH_VLAN_STRIP_MASK | RTE_ETH_VLAN_FILTER_MASK |
+ RTE_ETH_VLAN_EXTEND_MASK;
+
+ sxevf_vlan_offload_configure(eth_dev, vlan_mask);
+}
+
+s32 sxevf_promiscuous_enable(struct rte_eth_dev *eth_dev)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ s32 ret;
+
+ ret = sxevf_cast_mode_set(hw, SXEVF_CAST_MODE_PROMISC);
+ if (ret) {
+ LOG_ERROR_BDF("cast mode:0x%x set fail.(err:%d)",
+ SXEVF_CAST_MODE_PROMISC, ret);
+ }
+
+ return ret;
+}
+
+s32 sxevf_promiscuous_disable(struct rte_eth_dev *eth_dev)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ s32 mode = SXEVF_CAST_MODE_NONE;
+ s32 ret;
+
+ if (eth_dev->data->all_multicast)
+ mode = SXEVF_CAST_MODE_ALLMULTI;
+ ret = sxevf_cast_mode_set(hw, mode);
+ if (ret)
+ LOG_ERROR_BDF("disable mc promiscuous fail.(err:%d)", ret);
+
+ return ret;
+}
+
+s32 sxevf_allmulticast_enable(struct rte_eth_dev *eth_dev)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ s32 ret = 0;
+
+ if (eth_dev->data->promiscuous)
+ goto l_out;
+
+ ret = sxevf_cast_mode_set(hw, SXEVF_CAST_MODE_ALLMULTI);
+ if (ret)
+ LOG_ERROR_BDF("cast mode:0x%x set fail.(err:%d)",
+ SXEVF_CAST_MODE_ALLMULTI, ret);
+
+l_out:
+ return ret;
+}
+
+s32 sxevf_allmulticast_disable(struct rte_eth_dev *eth_dev)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ s32 ret = 0;
+
+ if (eth_dev->data->promiscuous)
+ goto l_out;
+
+ ret = sxevf_cast_mode_set(hw, SXEVF_CAST_MODE_MULTI);
+ if (ret)
+ LOG_ERROR_BDF("disable mc promiscuous fail.(err:%d)", ret);
+
+l_out:
+ return ret;
+}
+
+s32 sxevf_vlan_filter_set(struct rte_eth_dev *eth_dev, u16 vlan_id, s32 on)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ struct sxevf_vlan_context *vlan_ctxt = &adapter->vlan_ctxt;
+ s32 ret;
+ u8 reg_idx;
+ u8 bit_idx;
+
+ ret = sxevf_vlan_id_set(hw, vlan_id, on);
+ if (ret) {
+ LOG_ERROR_BDF("vlan_id:0x%x status:%u set fail.(err:%d)",
+ vlan_id, on, ret);
+ goto l_out;
+ }
+
+ reg_idx = (vlan_id >> SXEVF_VLAN_ID_SHIFT) & SXEVF_VLAN_ID_REG_MASK;
+ bit_idx = (vlan_id & SXEVF_VLAN_ID_BIT_MASK);
+
+ if (on)
+ vlan_ctxt->vlan_table[reg_idx] |= (1 << bit_idx);
+ else
+ vlan_ctxt->vlan_table[reg_idx] &= ~(1 << bit_idx);
+
+ LOG_INFO_BDF("vlan_id:0x%x status:%u set success.", vlan_id, on);
+
+l_out:
+ return ret;
+}
+
+void sxevf_vlan_strip_queue_set(struct rte_eth_dev *dev, u16 queue, s32 on)
+{
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+
+ if (queue > adapter->max_rx_queue) {
+ LOG_ERROR_BDF("queue id:%u invalid exceed max rx queue num:%u",
+ queue, adapter->max_rx_queue);
+ return;
+ }
+
+ sxevf_hw_vlan_tag_strip_switch(hw, queue, on);
+
+ sxevf_vlan_strip_bitmap_set(dev, queue, on);
+
+ LOG_INFO_BDF("queue:%u vlan tag strip on:%u done", queue, on);
+}
+
+static void sxevf_vlan_strip_offload_configure(struct rte_eth_dev *dev, s32 mask)
+{
+ u16 i;
+ struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
+ sxevf_rx_queue_s *rxq;
+
+ if (mask & RTE_ETH_VLAN_STRIP_MASK) {
+ if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) {
+ for (i = 0; i < dev->data->nb_rx_queues; i++) {
+ rxq = dev->data->rx_queues[i];
+ rxq->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
+ }
+ } else {
+ for (i = 0; i < dev->data->nb_rx_queues; i++) {
+ rxq = dev->data->rx_queues[i];
+ rxq->offloads &= ~RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
+ }
+ }
+ }
+
+ PMD_LOG_INFO(DRV, "mask:0x%x rx mode offload:0x%" SXE_PRIX64
+ " all queue vlan strip offload flag configure done",
+ mask, rxmode->offloads);
+}
+
+s32 sxevf_vlan_offload_set(struct rte_eth_dev *dev, s32 mask)
+{
+ sxevf_vlan_strip_offload_configure(dev, mask);
+
+ sxevf_vlan_offload_configure(dev, mask);
+
+ PMD_LOG_INFO(DRV, "vlan offload mask:0x%x set done.", mask);
+
+ return 0;
+}
+
+s32 sxevf_default_mac_addr_set(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mac_addr)
+{
+ s32 ret;
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ u8 *addr = mac_addr->addr_bytes;
+
+ UNUSED(addr);
+ ret = sxevf_mac_addr_set(hw, mac_addr->addr_bytes);
+ if (ret) {
+ LOG_ERROR_BDF("modify default mac addr to " RTE_ETHER_ADDR_PRT_FMT " fail.(err:%d)",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], ret);
+ }
+
+ LOG_INFO_BDF("modify default mac addr to " RTE_ETHER_ADDR_PRT_FMT " success.",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+ return ret;
+}
+
+s32 sxevf_mac_addr_add(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mac_addr,
+ __rte_unused u32 rar_idx, __rte_unused u32 pool)
+{
+ s32 ret;
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ struct sxevf_mac_filter_context *mac_ctxt = &adapter->mac_filter_ctxt;
+ u8 *addr = mac_addr->addr_bytes;
+
+ UNUSED(addr);
+ if (memcmp(mac_ctxt->def_mac_addr.addr_bytes, mac_addr->addr_bytes,
+ sizeof(*mac_addr)) == 0) {
+ ret = -EINVAL;
+ LOG_ERROR_BDF("mac_addr:" RTE_ETHER_ADDR_PRT_FMT " eaqual to defalut mac addr"
+ " skip mac addr add.(err:%d)",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], ret);
+ goto l_out;
+ }
+
+ ret = sxevf_uc_addr_add(hw, 2, mac_addr->addr_bytes);
+ if (ret) {
+ LOG_ERROR_BDF("mac_addr:" RTE_ETHER_ADDR_PRT_FMT " add fail.(err:%d)",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], ret);
+ goto l_out;
+ }
+
+ LOG_INFO_BDF("mac_addr:" RTE_ETHER_ADDR_PRT_FMT " add success.",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+l_out:
+ return ret;
+}
+
+void sxevf_mac_addr_remove(struct rte_eth_dev *dev, u32 index)
+{
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ struct sxevf_mac_filter_context *mac_ctxt = &adapter->mac_filter_ctxt;
+ struct rte_ether_addr *mac_addr;
+ u8 *addr;
+ u8 i;
+
+ sxevf_uc_addr_add(hw, 0, NULL);
+
+ for (i = 0, mac_addr = dev->data->mac_addrs; i < mac_ctxt->uc_table_size;
+ i++, mac_addr++) {
+ if (i == index || rte_is_zero_ether_addr(mac_addr) ||
+ (memcmp(mac_ctxt->def_mac_addr.addr_bytes, mac_addr->addr_bytes,
+ sizeof(*mac_addr)) == 0)) {
+ continue;
+ }
+ sxevf_uc_addr_add(hw, 2, mac_addr->addr_bytes);
+ }
+ addr = dev->data->mac_addrs[index].addr_bytes;
+ UNUSED(addr);
+ LOG_INFO_BDF("index:%u mac addr" RTE_ETHER_ADDR_PRT_FMT " remove success.",
+ index, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+}
+
+static u16 sxevf_hash_mac_addr_parse(u8 *mac_addr)
+{
+ u16 extracted = ((mac_addr[4] >> 4) |
+ (((u16)mac_addr[5]) << 4));
+
+ extracted &= SXEVF_MAC_ADDR_EXTRACT_MASK;
+
+ PMD_LOG_DEBUG(DRV, "mac_addr:" RTE_ETHER_ADDR_PRT_FMT " parse result:0x%x",
+ mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
+ mac_addr[4], mac_addr[5], extracted);
+
+ return extracted;
+}
+
+s32 sxevf_set_mc_addr_list(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mc_addr_list,
+ u32 nb_mc_addr)
+{
+ s32 ret;
+ u32 result;
+ struct sxevf_mc_sync_msg msg;
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ u32 i;
+
+ msg.msg_type = SXEVF_MC_ADDR_SYNC;
+ msg.mc_cnt = RTE_MIN(nb_mc_addr, (u32)SXEVF_MC_ENTRY_NUM_MAX);
+
+ for (i = 0; i < msg.mc_cnt; i++) {
+ msg.mc_addr_extract[i] = sxevf_hash_mac_addr_parse(mc_addr_list->addr_bytes);
+ mc_addr_list++;
+ }
+
+ ret = sxevf_send_and_rcv_msg(hw, (u32 *)&msg, SXEVF_MSG_NUM(sizeof(msg)));
+ result = (msg.mc_cnt << 16) | msg.msg_type;
+
+ if (ret || ((result & SXEVF_MC_ADDR_SYNC) &&
+ (result & SXEVF_MSGTYPE_NACK))) {
+ ret = ret ? ret : -SXEVF_ERR_MSG_HANDLE_ERR;
+ goto l_out;
+ }
+
+ PMD_LOG_DEBUG(DRV, "msg_type:0x%x len:%zu mc_cnt:%d msg "
+ "result:0x%x.(ret:%d)",
+ msg.msg_type, SXEVF_MSG_NUM(sizeof(msg)),
+ msg.mc_cnt, result, ret);
+
+l_out:
+ return ret;
+}
+
+#endif
diff --git a/drivers/net/sxe/vf/sxevf_filter.h b/drivers/net/sxe/vf/sxevf_filter.h
new file mode 100644
index 0000000000..d468be12cc
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_filter.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#ifndef __SXEVF_FILTER_H__
+#define __SXEVF_FILTER_H__
+
+#include <rte_ether.h>
+#include "sxe_dpdk_version.h"
+#include <ethdev_driver.h>
+#endif
+
+#define SXEVF_MTA_ENTRY_NUM_MAX 128
+#define SXEVF_UTA_HASH_BIT_MAX 4096
+#define VLAN_N_VID 4096
+#define BYTE_BIT_NUM 8
+
+#define SXEVF_VLAN_ID_SHIFT (5)
+#define SXEVF_VLAN_ID_REG_MASK (0x7F)
+#define SXEVF_VLAN_ID_BIT_MASK (0x1F)
+
+#define SXEVF_VLAN_STRIP_BITMAP_SIZE \
+ (SXEVF_HW_TXRX_RING_NUM_MAX / (sizeof(u32) * BYTE_BIT_NUM))
+
+struct sxevf_vlan_context {
+ u32 vlan_table[SXEVF_VFT_TBL_SIZE];
+ u32 strip_bitmap[SXEVF_VLAN_STRIP_BITMAP_SIZE];
+ u32 vlan_table_size;
+};
+
+struct sxevf_mac_filter_context {
+ struct rte_ether_addr def_mac_addr;
+ u8 mc_filter_type;
+ u32 uc_table_size;
+};
+
+void sxevf_vlan_filter_init(struct rte_eth_dev *eth_dev);
+
+s32 sxevf_mac_addr_init(struct rte_eth_dev *eth_dev);
+
+void sxevf_vlan_filter_configure(struct rte_eth_dev *eth_dev);
+
+void sxevf_vfta_sync(struct rte_eth_dev *eth_dev, bool on);
+
+s32 sxevf_promiscuous_disable(struct rte_eth_dev *eth_dev);
+
+s32 sxevf_promiscuous_enable(struct rte_eth_dev *eth_dev);
+
+s32 sxevf_allmulticast_disable(struct rte_eth_dev *eth_dev);
+
+s32 sxevf_allmulticast_enable(struct rte_eth_dev *eth_dev);
+
+s32 sxevf_vlan_filter_set(struct rte_eth_dev *eth_dev, u16 vlan_id, s32 on);
+
+void sxevf_vlan_strip_queue_set(struct rte_eth_dev *dev, u16 queue, s32 on);
+
+s32 sxevf_vlan_offload_set(struct rte_eth_dev *dev, s32 mask);
+
+s32 sxevf_default_mac_addr_set(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mac_addr);
+
+void sxevf_mac_addr_remove(struct rte_eth_dev *dev, u32 index);
+
+s32 sxevf_mac_addr_add(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mac_addr,
+ __rte_unused u32 rar_idx, __rte_unused u32 pool);
+
+s32 sxevf_set_mc_addr_list(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mc_addr_list,
+ u32 nb_mc_addr);
diff --git a/drivers/net/sxe/vf/sxevf_irq.c b/drivers/net/sxe/vf/sxevf_irq.c
new file mode 100644
index 0000000000..bf768a67f6
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_irq.c
@@ -0,0 +1,434 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#if defined SXE_DPDK_L4_FEATURES && defined SXE_DPDK_SRIOV
+
+#include <rte_ethdev.h>
+#include <rte_pci.h>
+#include <rte_alarm.h>
+#include <rte_interrupts.h>
+#include <rte_malloc.h>
+#include "sxe_dpdk_version.h"
+#include <bus_pci_driver.h>
+#include <eal_interrupts.h>
+
+#include "sxevf.h"
+#include "sxe_logs.h"
+#include "sxe_errno.h"
+#include "sxevf_rx.h"
+#include "sxevf_irq.h"
+#include "sxevf_msg.h"
+#include "sxevf_queue.h"
+#include "sxe_compat_version.h"
+
+#define SXEVF_IRQ_LINK_CONFIG (u32)(1 << 3)
+
+#define SXEVF_RX_OTHER_IRQ_MASK (3)
+
+#define SXEVF_MISC_VEC_ID RTE_INTR_VEC_ZERO_OFFSET
+
+#define SXEVF_RX_VEC_BASE RTE_INTR_VEC_RXTX_OFFSET
+
+#define SXEVF_EITR_INTERVAL_UNIT_NS 2048
+#define SXEVF_EITR_ITR_INT_SHIFT 3
+#define SXEVF_IRQ_ITR_MASK (0x00000FF8)
+#define SXEVF_EITR_INTERVAL_US(us) \
+ (((us) * 1000 / SXEVF_EITR_INTERVAL_UNIT_NS << SXEVF_EITR_ITR_INT_SHIFT) & \
+ SXEVF_IRQ_ITR_MASK)
+
+#define SXEVF_QUEUE_ITR_INTERVAL_DEFAULT 500
+#define SXEVF_QUEUE_ITR_INTERVAL 3
+
+void sxevf_intr_disable(struct rte_eth_dev *eth_dev)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ struct sxevf_irq_context *irq_ctxt = &adapter->irq_ctxt;
+
+ PMD_INIT_FUNC_TRACE();
+
+ sxevf_irq_disable(hw);
+
+ irq_ctxt->enable_mask = 0;
+}
+
+void sxevf_intr_enable(struct rte_eth_dev *eth_dev)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ struct sxevf_irq_context *irq_ctxt = &adapter->irq_ctxt;
+
+ PMD_INIT_FUNC_TRACE();
+
+ sxevf_irq_enable(hw, SXEVF_RX_OTHER_IRQ_MASK);
+
+ irq_ctxt->enable_mask = SXEVF_RX_OTHER_IRQ_MASK;
+}
+
+static s32 sxevf_ctrl_msg_check(struct rte_eth_dev *eth_dev)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ u32 ctrl_msg;
+ s32 ret;
+
+ ret = sxevf_ctrl_msg_rcv_and_clear(hw, (u32 *)&ctrl_msg,
+ SXEVF_MSG_NUM(sizeof(ctrl_msg)));
+ if (ret) {
+ PMD_LOG_INFO(DRV, "ctrl msg rcv fail due to lock fail.(err:%d)", ret);
+ goto l_end;
+ }
+
+ if (ctrl_msg & SXEVF_PF_CTRL_MSG_REINIT) {
+ sxe_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_INTR_RESET,
+ NULL);
+ PMD_LOG_INFO(DRV, "rcv reinit msg.");
+ }
+
+l_end:
+ return ret;
+}
+
+static s32 sxevf_link_msg_check(struct rte_eth_dev *eth_dev, bool *link_up)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ u32 ctrl_msg;
+ s32 ret;
+
+ ret = sxevf_ctrl_msg_rcv_and_clear(hw, (u32 *)&ctrl_msg,
+ SXEVF_MSG_NUM(sizeof(ctrl_msg)));
+ if (ret) {
+ PMD_LOG_INFO(DRV, "ctrl msg rcv fail due to lock fail.(err:%d)", ret);
+ goto l_end;
+ }
+
+ if (ctrl_msg & SXEVF_PF_CTRL_MSG_NETDEV_DOWN) {
+ *link_up = false;
+ PMD_LOG_INFO(DRV, "rcv ctrl msg:0x%x need link down.", ctrl_msg);
+ } else if (ctrl_msg & SXEVF_PF_CTRL_MSG_LINK_UPDATE) {
+ *link_up = true;
+ PMD_LOG_INFO(DRV, "rcv ctrl msg:0x%x physical link up.", ctrl_msg);
+ }
+
+l_end:
+ return ret;
+}
+
+static void sxevf_mbx_irq_handler(void *data)
+{
+ struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)data;
+
+ sxevf_intr_disable(eth_dev);
+
+ sxevf_ctrl_msg_check(eth_dev);
+
+ sxevf_intr_enable(eth_dev);
+}
+
+void sxevf_irq_init(struct rte_eth_dev *eth_dev)
+{
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+ struct rte_intr_handle *irq_handle = SXE_PCI_INTR_HANDLE(pci_dev);
+
+ sxevf_intr_disable(eth_dev);
+
+ rte_intr_callback_register(irq_handle,
+ sxevf_mbx_irq_handler, eth_dev);
+
+ rte_intr_enable(irq_handle);
+ sxevf_intr_enable(eth_dev);
+}
+
+static s32 sxevf_msix_configure(struct rte_eth_dev *dev)
+{
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+ struct rte_intr_handle *handle = SXE_PCI_INTR_HANDLE(pci_dev);
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ sxevf_rx_queue_s *rx_queue;
+ u16 queue_id;
+ u16 vector = SXEVF_MISC_VEC_ID;
+ u16 base = SXEVF_MISC_VEC_ID;
+ u32 irq_interval;
+ s32 ret = 0;
+
+ sxevf_event_irq_map(hw, vector);
+
+ if (!rte_intr_dp_is_en(handle)) {
+ ret = -SXE_ERR_PARAM;
+ PMD_LOG_ERR(DRV, "intr type:%u nb_efd:%u irq unsupported.(err:%d)",
+ handle->type, handle->nb_efd, ret);
+ goto l_out;
+ }
+
+ if (rte_intr_allow_others(handle)) {
+ vector = SXEVF_RX_VEC_BASE;
+ base = SXEVF_RX_VEC_BASE;
+ }
+
+ irq_interval = SXEVF_EITR_INTERVAL_US(SXEVF_QUEUE_ITR_INTERVAL_DEFAULT);
+ if (rte_intr_dp_is_en(handle))
+ irq_interval = SXEVF_EITR_INTERVAL_US(SXEVF_QUEUE_ITR_INTERVAL);
+
+ for (queue_id = 0; queue_id < dev->data->nb_rx_queues;
+ queue_id++) {
+ rx_queue = dev->data->rx_queues[queue_id];
+ if (rte_intr_dp_is_en(handle))
+ sxevf_ring_irq_interval_set(hw, vector, irq_interval);
+
+ sxevf_hw_ring_irq_map(hw, false,
+ rx_queue->reg_idx,
+ vector);
+ handle->intr_vec[queue_id] = vector;
+ PMD_LOG_INFO(DRV,
+ "queue id:%u reg_idx:%u vector:%u ",
+ queue_id,
+ rx_queue->reg_idx,
+ vector);
+ if (vector < base + handle->nb_efd - 1)
+ vector++;
+ }
+
+ sxevf_ring_irq_interval_set(hw, 0, irq_interval);
+
+l_out:
+ return ret;
+}
+
+s32 sxevf_irq_configure(struct rte_eth_dev *eth_dev)
+{
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+ struct rte_intr_handle *handle = SXE_PCI_INTR_HANDLE(pci_dev);
+ u16 irq_num;
+ s32 ret = 0;
+
+ if (rte_intr_cap_multiple(handle) &&
+ eth_dev->data->dev_conf.intr_conf.rxq != 0) {
+ irq_num = 1;
+ if (rte_intr_efd_enable(handle, irq_num)) {
+ ret = -SXE_ERR_CONFIG;
+ PMD_LOG_ERR(DRV,
+ "intr_handle type:%d irq num:%d invalid",
+ handle->type, irq_num);
+ goto l_out;
+ }
+ }
+
+ if (rte_intr_dp_is_en(handle) && !handle->intr_vec) {
+ handle->intr_vec = rte_zmalloc("intr_vec",
+ eth_dev->data->nb_rx_queues * sizeof(u32), 0);
+ if (handle->intr_vec == NULL) {
+ PMD_LOG_ERR(DRV, "rx queue irq vector "
+ "allocate %zuB memory fail.",
+ eth_dev->data->nb_rx_queues * sizeof(u32));
+ ret = -ENOMEM;
+ goto l_out;
+ }
+ }
+
+ ret = sxevf_msix_configure(eth_dev);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "intr type:%u nb_efd:%u irq unsupported.(err:%d)",
+ handle->type, handle->nb_efd, ret);
+ goto l_out;
+ }
+
+ rte_intr_disable(handle);
+
+ rte_intr_enable(handle);
+
+ sxevf_intr_enable(eth_dev);
+
+ PMD_LOG_INFO(DRV,
+ "intr_handle type:%d rx queue num:%d "
+ "queue irq num:%u total irq num:%u "
+ "config done",
+ handle->type,
+ eth_dev->data->nb_rx_queues,
+ handle->nb_efd,
+ handle->max_intr);
+
+l_out:
+ return ret;
+}
+
+void sxevf_irq_free(struct rte_eth_dev *eth_dev)
+{
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+ struct rte_intr_handle *handle = SXE_PCI_INTR_HANDLE(pci_dev);
+
+ rte_intr_disable(handle);
+
+ if (handle->intr_vec) {
+ rte_free(handle->intr_vec);
+ handle->intr_vec = NULL;
+ }
+}
+
+void sxevf_irq_unregister(struct rte_eth_dev *eth_dev)
+{
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
+ struct rte_intr_handle *handle = SXE_PCI_INTR_HANDLE(pci_dev);
+
+ rte_intr_callback_unregister(handle, sxevf_mbx_irq_handler, eth_dev);
+}
+
+s32 sxevf_rx_queue_intr_enable(struct rte_eth_dev *dev, u16 queue_id)
+{
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+ struct rte_intr_handle *intr_handle = SXE_PCI_INTR_HANDLE(pci_dev);
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ struct sxevf_irq_context *irq_ctxt = &adapter->irq_ctxt;
+ u32 vector = SXEVF_MISC_VEC_ID;
+
+ RTE_SET_USED(queue_id);
+
+ if (rte_intr_allow_others(intr_handle))
+ vector = SXEVF_RX_VEC_BASE;
+
+ irq_ctxt->enable_mask |= (1 << vector);
+
+ sxevf_specific_irq_enable(hw, irq_ctxt->enable_mask);
+
+ rte_intr_ack(intr_handle);
+
+ return 0;
+}
+
+s32 sxevf_rx_queue_intr_disable(struct rte_eth_dev *dev, u16 queue_id)
+{
+ struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+ struct rte_intr_handle *intr_handle = SXE_PCI_INTR_HANDLE(pci_dev);
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ struct sxevf_irq_context *irq_ctxt = &adapter->irq_ctxt;
+ u32 vector = SXEVF_MISC_VEC_ID;
+
+ RTE_SET_USED(queue_id);
+
+ if (rte_intr_allow_others(intr_handle))
+ vector = SXEVF_RX_VEC_BASE;
+
+ irq_ctxt->enable_mask &= ~(1 << vector);
+
+ sxevf_specific_irq_enable(hw, irq_ctxt->enable_mask);
+
+ return 0;
+}
+
+static void sxevf_physical_link_check(struct rte_eth_dev *dev, u32 *link_speed, bool *link_up)
+{
+ u32 link_reg, i;
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+
+ link_reg = sxevf_link_state_get(hw);
+ if (!(link_reg & SXE_VFLINKS_UP)) {
+ *link_up = false;
+ goto l_end;
+ }
+
+ for (i = 0; i < 5; i++) {
+ sxe_udelay(100);
+ link_reg = sxevf_link_state_get(hw);
+ if (!(link_reg & SXE_VFLINKS_UP)) {
+ *link_up = false;
+ goto l_end;
+ }
+ }
+
+ switch (link_reg & SXE_VFLINKS_SPEED) {
+ case SXE_VFLINKS_SPEED_10G:
+ *link_speed = SXEVF_LINK_SPEED_10GB_FULL;
+ break;
+ case SXE_VFLINKS_SPEED_1G:
+ *link_speed = SXEVF_LINK_SPEED_1GB_FULL;
+ break;
+ case SXE_VFLINKS_SPEED_100:
+ *link_speed = SXEVF_LINK_SPEED_100_FULL;
+ break;
+ default:
+ *link_speed = SXEVF_LINK_SPEED_UNKNOWN;
+ }
+
+ *link_up = true;
+
+l_end:
+ PMD_LOG_INFO(DRV, "link up status:%d.", *link_up);
+}
+
+static void sxevf_link_info_get(struct rte_eth_dev *dev, int wait_to_complete,
+ u32 *link_speed, bool *link_up)
+{
+ s32 ret;
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+
+ sxevf_physical_link_check(dev, link_speed, link_up);
+
+ if (wait_to_complete == 0 && adapter->link_check == 0) {
+ if (*link_speed == SXEVF_LINK_SPEED_UNKNOWN)
+ *link_up = false;
+ else
+ *link_up = true;
+ return;
+ }
+
+ if (*link_up) {
+ ret = sxevf_link_msg_check(dev, link_up);
+ if (ret) {
+ PMD_LOG_ERR(DRV, "ctrl msg rcv fail, try to next workqueue.");
+ return;
+ }
+ }
+}
+
+s32 sxevf_link_update(struct rte_eth_dev *dev, int wait_to_complete)
+{
+ bool link_up;
+ struct rte_eth_link link;
+ u32 link_speed = SXEVF_LINK_SPEED_UNKNOWN;
+
+ PMD_LOG_INFO(INIT, "link update start...");
+
+ memset(&link, 0, sizeof(link));
+ link.link_status = RTE_ETH_LINK_DOWN;
+ link.link_speed = RTE_ETH_SPEED_NUM_NONE;
+ link.link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
+ link.link_autoneg = !(dev->data->dev_conf.link_speeds &
+ RTE_ETH_LINK_SPEED_FIXED);
+
+ if (wait_to_complete == 0 || dev->data->dev_conf.intr_conf.lsc)
+ wait_to_complete = 0;
+
+ sxevf_link_info_get(dev, wait_to_complete, &link_speed, &link_up);
+
+ if (!link_up) {
+ PMD_LOG_ERR(DRV, "other link thread is running now!");
+
+ goto l_end;
+ }
+
+ link.link_status = RTE_ETH_LINK_UP;
+ link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
+ switch (link_speed) {
+ case SXEVF_LINK_SPEED_1GB_FULL:
+ link.link_speed = RTE_ETH_SPEED_NUM_1G;
+ break;
+
+ case SXEVF_LINK_SPEED_10GB_FULL:
+ link.link_speed = RTE_ETH_SPEED_NUM_10G;
+ break;
+ default:
+ link.link_speed = RTE_ETH_SPEED_NUM_UNKNOWN;
+ }
+
+l_end:
+ PMD_LOG_INFO(DRV, "link update end, up=%x, speed=%x",
+ link_up, link_speed);
+ return rte_eth_linkstatus_set(dev, &link);
+}
+
+#endif
diff --git a/drivers/net/sxe/vf/sxevf_irq.h b/drivers/net/sxe/vf/sxevf_irq.h
new file mode 100644
index 0000000000..def1167af7
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_irq.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#ifndef __SXEVF_IRQ_H__
+#define __SXEVF_IRQ_H__
+
+#include "sxe_dpdk_version.h"
+#include <ethdev_driver.h>
+#include "sxe_compat_platform.h"
+
+struct sxevf_irq_context {
+ u32 enable_mask;
+ u32 enable_mask_original;
+};
+
+void sxevf_intr_disable(struct rte_eth_dev *eth_dev);
+
+void sxevf_intr_enable(struct rte_eth_dev *eth_dev);
+
+void sxevf_irq_init(struct rte_eth_dev *eth_dev);
+
+s32 sxevf_irq_configure(struct rte_eth_dev *eth_dev);
+
+void sxevf_irq_free(struct rte_eth_dev *eth_dev);
+
+void sxevf_irq_unregister(struct rte_eth_dev *eth_dev);
+
+s32 sxevf_rx_queue_intr_disable(struct rte_eth_dev *dev, u16 queue_id);
+
+s32 sxevf_rx_queue_intr_enable(struct rte_eth_dev *dev, u16 queue_id);
+
+s32 sxevf_link_update(struct rte_eth_dev *dev, int wait_to_complete);
+
+#endif
diff --git a/drivers/net/sxe/vf/sxevf_main.c b/drivers/net/sxe/vf/sxevf_main.c
new file mode 100644
index 0000000000..d418705cf8
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_main.c
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#if defined SXE_DPDK_L4_FEATURES && defined SXE_DPDK_SRIOV
+
+#include <string.h>
+#include <sys/time.h>
+
+#include <rte_log.h>
+#include <rte_pci.h>
+#include <rte_dev.h>
+
+#include "sxe_version.h"
+#include "sxe_dpdk_version.h"
+#include <ethdev_driver.h>
+#include <ethdev_pci.h>
+#include <bus_pci_driver.h>
+
+#include "sxevf.h"
+#include "sxe_logs.h"
+#include "sxevf_ethdev.h"
+#include "sxe_queue_common.h"
+
+#define PCI_VENDOR_ID_STARS 0x1FF2
+#define SXEVF_DEV_ID_ASIC 0x10A2
+
+static s32 sxevf_probe(struct rte_pci_driver *pci_drv __rte_unused,
+ struct rte_pci_device *pci_dev)
+{
+ s32 ret;
+
+ PMD_LOG_INFO(INIT, "sxe_version[%s], sxe_commit_id[%s], sxe_branch[%s], sxe_build_time[%s]",
+ SXE_VERSION, SXE_COMMIT_ID, SXE_BRANCH, SXE_BUILD_TIME);
+
+#ifdef SXE_DPDK_DEBUG
+ sxe_log_stream_init();
+#endif
+
+ ret = rte_eth_dev_pci_generic_probe(pci_dev,
+ sizeof(struct sxevf_adapter), sxevf_ethdev_init);
+ if (ret) {
+ PMD_LOG_ERR(INIT, "sxe pmd eth dev create fail.(err:%d)", ret);
+ goto l_out;
+ }
+
+ PMD_LOG_DEBUG(INIT, "%s sxevf pmd probe done.", pci_dev->device.name);
+
+l_out:
+ return ret;
+}
+
+static s32 sxevf_remove(struct rte_pci_device *pci_dev)
+{
+ s32 ret;
+
+ ret = rte_eth_dev_pci_generic_remove(pci_dev,
+ sxevf_ethdev_uninit);
+ if (ret)
+ LOG_ERROR("vf remove fail.(err:%d)", ret);
+
+ return ret;
+}
+
+static const struct rte_pci_id sxevf_pci_tbl[] = {
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_STARS, SXEVF_DEV_ID_ASIC) },
+ {.vendor_id = 0,}
+};
+
+static struct rte_pci_driver rte_sxevf_pmd = {
+ .id_table = sxevf_pci_tbl,
+ .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
+ .probe = sxevf_probe,
+ .remove = sxevf_remove,
+};
+
+RTE_PMD_REGISTER_PCI(net_sxevf, rte_sxevf_pmd);
+RTE_PMD_REGISTER_PCI_TABLE(net_sxevf, sxevf_pci_tbl);
+RTE_PMD_REGISTER_KMOD_DEP(net_sxevf, "* igb_uio | vfio-pci");
+RTE_PMD_REGISTER_PARAM_STRING(net_sxevf,
+ SXEVF_DEVARG_LINK_CHECK "=<0|1>");
+
+#endif
diff --git a/drivers/net/sxe/vf/sxevf_msg.c b/drivers/net/sxe/vf/sxevf_msg.c
new file mode 100644
index 0000000000..faf6787e74
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_msg.c
@@ -0,0 +1,624 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#if defined SXE_DPDK_L4_FEATURES && defined SXE_DPDK_SRIOV
+
+#include "sxevf.h"
+#include "sxevf_msg.h"
+#include "sxevf_hw.h"
+#include "sxe_errno.h"
+#include "sxe_logs.h"
+
+#define SXEVF_PFMSG_MASK 0xFF00
+#define SXEVF_DEFAULT_TC_NUM 1
+
+void sxevf_mbx_init(struct sxevf_hw *hw)
+{
+ hw->mbx.msg_len = SXEVF_MBX_MSG_NUM;
+
+ hw->mbx.stats.rcv_msgs = 0;
+ hw->mbx.stats.send_msgs = 0;
+ hw->mbx.stats.acks = 0;
+ hw->mbx.stats.reqs = 0;
+ hw->mbx.stats.rsts = 0;
+
+ hw->mbx.retry = 0;
+ hw->mbx.interval = SXEVF_MBX_RETRY_INTERVAL;
+
+ hw->mbx.api_version = SXEVF_MBX_API_10;
+}
+
+static u32 sxevf_mbx_reg_read(struct sxevf_hw *hw)
+{
+ u32 value = sxevf_mailbox_read(hw);
+
+ value |= hw->mbx.reg_value;
+
+ hw->mbx.reg_value |= value & SXE_VFMAILBOX_RC_BIT;
+
+ return value;
+}
+
+static bool sxevf_mbx_bit_check(struct sxevf_hw *hw, u32 mask)
+{
+ bool ret = false;
+ u32 value = sxevf_mbx_reg_read(hw);
+
+ if (value & mask)
+ ret = true;
+
+ hw->mbx.reg_value &= ~mask;
+
+ return ret;
+}
+
+static bool sxevf_pf_msg_check(struct sxevf_hw *hw)
+{
+ bool ret = false;
+
+ if (sxevf_mbx_bit_check(hw, SXE_VFMAILBOX_PFSTS)) {
+ hw->mbx.stats.reqs++;
+ ret = true;
+ }
+
+ return ret;
+}
+
+static bool sxevf_pf_ack_check(struct sxevf_hw *hw)
+{
+ bool ret = false;
+
+ if (sxevf_mbx_bit_check(hw, SXE_VFMAILBOX_PFACK)) {
+ hw->mbx.stats.acks++;
+ ret = true;
+ }
+
+ return ret;
+}
+
+bool sxevf_pf_rst_check(struct sxevf_hw *hw)
+{
+ bool ret = false;
+
+ if (!sxevf_mbx_bit_check(hw, (SXE_VFMAILBOX_RSTI |
+ SXE_VFMAILBOX_RSTD))) {
+ hw->mbx.stats.rsts++;
+ ret = true;
+ }
+
+ return ret;
+}
+
+static s32 sxevf_mailbox_lock(struct sxevf_hw *hw)
+{
+ u32 mailbox;
+ u32 retry = SXEVF_MBX_RETRY_COUNT;
+ s32 ret = -SXEVF_ERR_MBX_LOCK_FAIL;
+
+ while (retry--) {
+ mailbox = sxevf_mbx_reg_read(hw);
+ mailbox |= SXE_VFMAILBOX_VFU;
+ sxevf_mailbox_write(hw, mailbox);
+
+ if (sxevf_mbx_reg_read(hw) && SXE_VFMAILBOX_VFU) {
+ ret = 0;
+ break;
+ }
+
+ sxe_udelay(hw->mbx.interval);
+ }
+
+ return ret;
+}
+
+static void sxevf_mailbox_unlock(struct sxevf_hw *hw)
+{
+ u32 mailbox;
+
+ mailbox = sxevf_mbx_reg_read(hw);
+ mailbox &= ~SXE_VFMAILBOX_VFU;
+ sxevf_mailbox_write(hw, mailbox);
+}
+
+static bool sxevf_msg_poll(struct sxevf_hw *hw)
+{
+ struct sxevf_mbx_info *mbx = &hw->mbx;
+ u32 retry = mbx->retry;
+ bool ret = true;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ while (!sxevf_pf_msg_check(hw) && retry) {
+ retry--;
+ sxe_udelay(mbx->interval);
+ }
+
+ if (!retry) {
+ LOG_ERROR_BDF("retry:%d send msg to pf done, but don't check pf reply.",
+ mbx->retry);
+ mbx->retry = 0;
+ ret = false;
+ }
+
+ return ret;
+}
+
+static bool sxevf_ack_poll(struct sxevf_hw *hw)
+{
+ struct sxevf_mbx_info *mbx = &hw->mbx;
+ u32 retry = mbx->retry;
+ bool ret = true;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ while (!sxevf_pf_ack_check(hw) && retry) {
+ retry--;
+ sxe_udelay(mbx->interval);
+ }
+
+ if (!retry) {
+ LOG_ERROR_BDF("send msg to pf, retry:%d but don't check pf ack, "
+ "init mbx retry to 0.",
+ mbx->retry);
+ mbx->retry = 0;
+ ret = false;
+ }
+
+ return ret;
+}
+
+static void sxevf_pf_msg_and_ack_clear(struct sxevf_hw *hw)
+{
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ LOG_INFO_BDF("clear pending pf msg and ack.");
+
+ sxevf_pf_msg_check(hw);
+ sxevf_pf_ack_check(hw);
+}
+
+static s32 sxevf_send_msg_to_pf(struct sxevf_hw *hw, u32 *msg, u16 msg_len)
+{
+ struct sxevf_mbx_info *mbx = &hw->mbx;
+ s32 ret = 0;
+ u16 i;
+ u32 old;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ if (!mbx->retry) {
+ ret = -SXEVF_ERR_NOT_READY;
+ LOG_ERROR_BDF("msg:0x%x len:%d send fail due to timeout.(err:%d)",
+ msg[0], msg_len, ret);
+ goto l_out;
+ }
+
+ if (msg_len > mbx->msg_len) {
+ ret = -EINVAL;
+ LOG_ERROR_BDF("vf msg:0x%x len:%d exceed limit:%d "
+ "send fail.(err:%d)",
+ msg[0], msg_len, mbx->msg_len, ret);
+ goto l_out;
+ }
+
+ ret = sxevf_mailbox_lock(hw);
+ if (ret) {
+ LOG_ERROR_BDF("msg:0x%x len:%d send lock mailbox fail.(err:%d)",
+ msg[0], msg_len, ret);
+ goto l_out;
+ }
+
+ sxevf_pf_msg_and_ack_clear(hw);
+
+ old = sxevf_msg_read(hw, 0);
+ msg[0] |= (old & SXEVF_PFMSG_MASK);
+
+ for (i = 0; i < msg_len; i++)
+ sxevf_msg_write(hw, i, msg[i]);
+
+ sxevf_pf_req_irq_trigger(hw);
+
+ hw->mbx.stats.send_msgs++;
+
+ if (!sxevf_ack_poll(hw)) {
+ ret = -SXEVF_ERR_POLL_ACK_FAIL;
+ LOG_ERROR_BDF("msg:0x%x len:%d send done, but don't poll ack.",
+ msg[0], msg_len);
+ goto l_out;
+ }
+
+ LOG_INFO_BDF("vf send msg:0x%x len:%d to pf and polled pf ack done."
+ "stats send_msg:%d ack:%d.",
+ msg[0], msg_len,
+ mbx->stats.send_msgs, mbx->stats.acks);
+
+l_out:
+ return ret;
+}
+
+s32 sxevf_mbx_msg_rcv(struct sxevf_hw *hw, u32 *msg, u16 msg_len)
+{
+ u32 i;
+ u16 msg_entry;
+ s32 ret = 0;
+ struct sxevf_mbx_info *mbx = &hw->mbx;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ msg_entry = (msg_len > mbx->msg_len) ? mbx->msg_len : msg_len;
+
+ ret = sxevf_mailbox_lock(hw);
+ if (ret) {
+ LOG_ERROR_BDF("size:%d rcv lock mailbox fail.(err:%d)",
+ msg_entry, ret);
+ goto l_end;
+ }
+
+ for (i = 0; i < msg_entry; i++)
+ msg[i] = sxevf_msg_read(hw, i);
+
+ msg[0] &= ~SXEVF_PFMSG_MASK;
+
+ sxevf_pf_ack_irq_trigger(hw);
+
+ mbx->stats.rcv_msgs++;
+l_end:
+ return ret;
+}
+
+s32 sxevf_ctrl_msg_rcv(struct sxevf_hw *hw, u32 *msg, u16 msg_len)
+{
+ u16 i;
+ u16 msg_entry;
+ s32 ret = 0;
+ struct sxevf_mbx_info *mbx = &hw->mbx;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ msg_entry = (msg_len > mbx->msg_len) ? mbx->msg_len : msg_len;
+
+ ret = sxevf_mailbox_lock(hw);
+ if (ret) {
+ LOG_ERROR_BDF("size:%d rcv lock mailbox fail.(err:%d)",
+ msg_entry, ret);
+ goto l_end;
+ }
+
+ for (i = 0; i < msg_entry; i++)
+ msg[i] = sxevf_msg_read(hw, i);
+
+ sxevf_mailbox_unlock(hw);
+
+ LOG_INFO_BDF("rcv pf mailbox msg:0x%x.", *msg);
+
+ mbx->stats.rcv_msgs++;
+l_end:
+ return ret;
+}
+
+s32 sxevf_ctrl_msg_rcv_and_clear(struct sxevf_hw *hw, u32 *msg, u16 msg_len)
+{
+ u16 i;
+ u16 msg_entry;
+ s32 ret = 0;
+ u32 clear;
+ struct sxevf_mbx_info *mbx = &hw->mbx;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ msg_entry = (msg_len > mbx->msg_len) ? mbx->msg_len : msg_len;
+
+ ret = sxevf_mailbox_lock(hw);
+ if (ret) {
+ LOG_ERROR_BDF("size:%d rcv lock mailbox fail.(err:%d)",
+ msg_entry, ret);
+ goto l_end;
+ }
+
+ for (i = 0; i < msg_entry; i++)
+ msg[i] = sxevf_msg_read(hw, i);
+
+ clear = msg[0] & (~SXEVF_PFMSG_MASK);
+ sxevf_msg_write(hw, 0, clear);
+
+ sxevf_mailbox_unlock(hw);
+
+ LOG_INFO_BDF("rcv pf mailbox msg:0x%x.", *msg);
+
+ mbx->stats.rcv_msgs++;
+l_end:
+ return ret;
+}
+
+static s32 sxevf_rcv_msg_from_pf(struct sxevf_hw *hw, u32 *msg, u16 msg_len)
+{
+ s32 ret;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ if (!sxevf_msg_poll(hw)) {
+ ret = -SXEVF_ERR_POLL_MSG_FAIL;
+ LOG_ERROR_BDF("retry:%d don't poll pf msg.", hw->mbx.retry);
+ goto l_out;
+ }
+
+ ret = sxevf_mbx_msg_rcv(hw, msg, msg_len);
+ if (ret < 0) {
+ LOG_ERROR_BDF("retry:%d read msg fail.", hw->mbx.retry);
+ goto l_out;
+ }
+
+ LOG_INFO_BDF("vf polled pf msg:0x%x and rcv pf msg done. "
+ "stats req:%d rcv_msg:%d",
+ msg[0], hw->mbx.stats.reqs, hw->mbx.stats.rcv_msgs);
+
+l_out:
+ return ret;
+}
+
+s32 sxevf_send_and_rcv_msg(struct sxevf_hw *hw, u32 *msg, u8 msg_len)
+{
+ s32 ret;
+ u16 msg_type = msg[0] & 0xFF;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ ret = sxevf_send_msg_to_pf(hw, msg, msg_len);
+ if (ret) {
+ LOG_ERROR_BDF("msg:0x%x len:%u msg send fail.(err:%d).",
+ msg[0], msg_len, ret);
+ goto l_out;
+ }
+
+ if (msg_type == SXEVF_RESET)
+ mdelay(10);
+
+ ret = sxevf_rcv_msg_from_pf(hw, msg, msg_len);
+ if (ret) {
+ LOG_ERROR_BDF("msg:0x%x len:%u rcv fail.(err:%d).",
+ msg[0], msg_len, ret);
+ goto l_out;
+ }
+
+ LOG_INFO_BDF("send and rcv msg:0x%x len:%u success.", msg[0], msg_len);
+
+l_out:
+ return ret;
+}
+
+void sxevf_mbx_api_version_init(struct sxevf_adapter *adapter)
+{
+ s32 ret;
+ struct sxevf_hw *hw = &adapter->hw;
+ static const int api[] = {
+ SXEVF_MBX_API_13,
+ SXEVF_MBX_API_12,
+ SXEVF_MBX_API_11,
+ SXEVF_MBX_API_10,
+ SXEVF_MBX_API_NR
+ };
+ u32 idx = 0;
+ struct sxevf_mbx_api_msg msg;
+
+ while (api[idx] != SXEVF_MBX_API_NR) {
+ msg.msg_type = SXEVF_API_NEGOTIATE;
+ msg.api_version = api[idx];
+
+ ret = sxevf_send_and_rcv_msg(hw, (u32 *)&msg, SXEVF_MSG_NUM(sizeof(msg)));
+ if (!ret && (msg.msg_type == (SXEVF_API_NEGOTIATE | SXEVF_MSGTYPE_ACK))) {
+ hw->mbx.api_version = api[idx];
+ break;
+ }
+ idx++;
+ }
+
+ LOG_INFO_BDF("mailbox api version:%u", hw->mbx.api_version);
+}
+
+s32 sxevf_ring_info_get(struct sxevf_adapter *adapter,
+ u8 *tc_num, u8 *default_tc)
+{
+ struct sxevf_hw *hw = &adapter->hw;
+ struct sxevf_ring_info_msg req = {};
+ s32 ret;
+
+ req.msg_type = SXEVF_RING_INFO_GET;
+ ret = sxevf_send_and_rcv_msg(hw, (u32 *)&req,
+ SXEVF_MSG_NUM(sizeof(req)));
+ if (ret) {
+ LOG_ERROR_BDF("msg:0x%x send or rcv reply failed.(err:%d)",
+ req.msg_type, ret);
+ goto l_out;
+ }
+
+ if (req.msg_type != (SXEVF_MSGTYPE_ACK | SXEVF_RING_INFO_GET)) {
+ ret = -SXEVF_ERR_REPLY_INVALID;
+ LOG_WARN_BDF("msg:0x%x not expected.(err:%d)", req.msg_type, ret);
+ goto l_out;
+ }
+
+ LOG_DEBUG_BDF("original ring info from pf, max_tx_num:%u max_rx_num:%u "
+ "tc_num:%u default_tc:%u.",
+ req.max_tx_num, req.max_rx_num, req.tc_num, req.default_tc);
+
+ if (req.max_tx_num == 0 ||
+ req.max_tx_num > SXEVF_TXRX_RING_NUM_MAX) {
+ req.max_tx_num = SXEVF_TXRX_RING_NUM_MAX;
+ }
+
+ if (req.max_rx_num == 0 ||
+ req.max_rx_num > SXEVF_TXRX_RING_NUM_MAX) {
+ req.max_rx_num = SXEVF_TXRX_RING_NUM_MAX;
+ }
+
+ if (req.tc_num > req.max_rx_num)
+ req.tc_num = SXEVF_DEFAULT_TC_NUM;
+
+ *tc_num = req.tc_num;
+
+ if (req.default_tc > req.max_tx_num)
+ req.default_tc = 0;
+
+ *default_tc = req.default_tc;
+
+ adapter->max_rx_queue = req.max_rx_num;
+ adapter->max_tx_queue = req.max_tx_num;
+
+ LOG_INFO_BDF("ring info max_tx_num:%u max_rx_num:%u "
+ "tc_num:%u default_tc:%u.",
+ req.max_tx_num, req.max_rx_num, req.tc_num, req.default_tc);
+
+l_out:
+ return ret;
+}
+
+s32 sxevf_rss_hash_config_get(struct sxevf_adapter *adapter,
+ struct rte_eth_rss_conf *rss_conf)
+{
+ struct sxevf_hw *hw = &adapter->hw;
+ struct sxevf_rss_hash_msg msg = {};
+ s32 ret;
+
+ msg.msg_type = SXEVF_RSS_CONF_GET;
+ ret = sxevf_send_and_rcv_msg(hw, (u32 *)&msg,
+ SXEVF_MSG_NUM(sizeof(msg)));
+ if (ret) {
+ LOG_ERROR_BDF("msg:0x%x send or rcv reply failed.(err:%d)",
+ msg.msg_type, ret);
+ goto l_out;
+ }
+
+ if (msg.msg_type != (SXEVF_MSGTYPE_ACK | SXEVF_RSS_CONF_GET)) {
+ ret = -SXEVF_ERR_REPLY_INVALID;
+ LOG_WARN_BDF("msg:0x%x not expected.(err:%d)", msg.msg_type, ret);
+ goto l_out;
+ }
+
+ rss_conf->rss_key = msg.hash_key;
+ rss_conf->rss_hf = msg.rss_hf;
+
+ LOG_INFO_BDF("rss hash conf get success, msg:0x%x rss_key:%s rss_func:%" SXE_PRID64 ". ",
+ msg.msg_type, msg.hash_key, msg.rss_hf);
+
+l_out:
+ return ret;
+}
+
+s32 sxevf_mac_addr_set(struct sxevf_hw *hw, u8 *uc_addr)
+{
+ s32 ret;
+ struct sxevf_uc_addr_msg msg = {};
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ msg.msg_type = SXEVF_DEV_MAC_ADDR_SET;
+ memcpy(msg.uc_addr, uc_addr, SXEVF_MAC_ADDR_LEN);
+
+ ret = sxevf_send_and_rcv_msg(hw, (u32 *)&msg, SXEVF_MSG_NUM(sizeof(msg)));
+ if (!ret && (msg.msg_type ==
+ (SXEVF_DEV_MAC_ADDR_SET | SXEVF_MSGTYPE_NACK))) {
+ ret = -EPERM;
+ LOG_ERROR_BDF("msg:0x%x uc addr:%pM replyed nack.",
+ msg.msg_type, uc_addr);
+ goto l_out;
+ }
+
+ if (ret) {
+ LOG_ERROR_BDF("msg:0x%x uc addr:%pM set fail.(err:%d)",
+ msg.msg_type, uc_addr, ret);
+ ret = -EPERM;
+ goto l_out;
+ }
+
+ LOG_INFO_BDF("msg:0x%x uc addr:%pM set success.", msg.msg_type, uc_addr);
+
+l_out:
+ return ret;
+}
+
+s32 sxevf_rx_max_frame_set(struct sxevf_hw *hw, u32 mtu)
+{
+ struct sxevf_max_frame_msg msg = {};
+ s32 ret;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ msg.msg_type = SXEVF_LPE_SET;
+ msg.max_frame = mtu;
+
+ ret = sxevf_send_and_rcv_msg(hw, (u32 *)&msg,
+ SXEVF_MSG_NUM(sizeof(msg)));
+ if (ret || ((msg.msg_type & SXEVF_LPE_SET) &&
+ (msg.msg_type & SXEVF_MSGTYPE_NACK))) {
+ ret = ret ? ret : -SXEVF_ERR_MSG_HANDLE_ERR;
+ }
+
+ LOG_INFO_BDF("msg_type:0x%x max_frame:0x%x (ret:%d)",
+ msg.msg_type, msg.max_frame, ret);
+
+ return ret;
+}
+
+s32 sxevf_vlan_id_set(struct sxevf_hw *hw, u32 vlan_id,
+ bool vlan_on)
+{
+ struct sxevf_vlan_filter_msg msg = {};
+ s32 ret;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ msg.msg_type = SXEVF_VLAN_SET;
+ msg.vlan_id = vlan_id;
+ msg.msg_type |= vlan_on << SXEVF_MSGINFO_SHIFT;
+
+ LOG_INFO_BDF("update vlan[%u], vlan on = %s", vlan_id, vlan_on ? "yes" : "no");
+ ret = sxevf_send_and_rcv_msg(hw, (u32 *)&msg,
+ SXEVF_MSG_NUM(sizeof(msg)));
+ LOG_INFO_BDF("update vlan[%u] ret = %d", vlan_id, ret);
+
+ msg.msg_type &= ~(0xFF << SXEVF_MSGINFO_SHIFT);
+
+ if (ret || (msg.msg_type != (SXEVF_VLAN_SET | SXEVF_MSGTYPE_ACK)))
+ ret = ret ? ret : -SXEVF_ERR_MSG_HANDLE_ERR;
+
+ return ret;
+}
+
+s32 sxevf_cast_mode_set(struct sxevf_hw *hw, enum sxevf_cast_mode mode)
+{
+ struct sxevf_cast_mode_msg msg = {};
+ s32 ret;
+ struct sxevf_adapter *adapter = hw->adapter;
+
+ msg.msg_type = SXEVF_CAST_MODE_SET;
+ msg.cast_mode = mode;
+
+ ret = sxevf_send_and_rcv_msg(hw, (u32 *)&msg, SXEVF_MSG_NUM(sizeof(msg)));
+ if (ret || (msg.msg_type != (SXEVF_CAST_MODE_SET | SXEVF_MSGTYPE_ACK)))
+ ret = ret ? ret : -SXEVF_ERR_MSG_HANDLE_ERR;
+
+ LOG_INFO_BDF("msg_type:0x%x mode:0x%x msg result:0x%x.(ret:%d)",
+ msg.msg_type, mode, msg.msg_type, ret);
+
+ return ret;
+}
+
+s32 sxevf_uc_addr_add(struct sxevf_hw *hw, u32 index, u8 *mac_addr)
+{
+ s32 ret = 0;
+ struct sxevf_adapter *adapter = hw->adapter;
+ struct sxevf_uc_sync_msg msg = {};
+ u32 check;
+ u32 result;
+
+ msg.msg_type = SXEVF_UC_ADDR_SYNC;
+ msg.index = index;
+ check = *(u32 *)&msg;
+
+ if (mac_addr)
+ memcpy((u8 *)&msg.addr, mac_addr, SXEVF_MAC_ADDR_LEN);
+
+ ret = sxevf_send_and_rcv_msg(hw, (u32 *)&msg, SXEVF_MSG_NUM(sizeof(msg)));
+ result = *(u32 *)&msg;
+
+ if (ret || (result != (check | SXEVF_MSGTYPE_ACK)))
+ ret = ret ? ret : -SXEVF_ERR_MSG_HANDLE_ERR;
+
+ LOG_INFO_BDF("msg_type:0x%x index:%d addr:%pM sync done "
+ " result:0x%x msg.(ret:%d)",
+ msg.msg_type, index, mac_addr, result, ret);
+
+ return ret;
+}
+
+#endif
diff --git a/drivers/net/sxe/vf/sxevf_msg.h b/drivers/net/sxe/vf/sxevf_msg.h
new file mode 100644
index 0000000000..f017117dff
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_msg.h
@@ -0,0 +1,201 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+#ifndef __SXEVF_MSG_H__
+#define __SXEVF_MSG_H__
+
+struct sxevf_adapter;
+
+#define SXEVF_MAC_ADDR_LEN 6
+
+#define SXEVF_UC_ENTRY_NUM_MAX 10
+#define SXEVF_MC_ENTRY_NUM_MAX 30
+
+#define SXEVF_MBX_MSG_NUM 16
+#define SXEVF_MBX_RETRY_INTERVAL 500
+#define SXEVF_MBX_RETRY_COUNT 2000
+
+#define SXEVF_RST_CHECK_NUM 10000
+
+#define SXEVF_DEFAULT_ADDR_LEN 4
+#define SXEVF_MC_FILTER_TYPE_WORD 3
+
+#define SXEVF_RESET 0x01
+#define SXEVF_DEV_MAC_ADDR_SET 0x02
+#define SXEVF_MC_ADDR_SYNC 0x03
+#define SXEVF_VLAN_SET 0x04
+#define SXEVF_LPE_SET 0x05
+
+#define SXEVF_UC_ADDR_SYNC 0x06
+
+#define SXEVF_API_NEGOTIATE 0x08
+
+#define SXEVF_RING_INFO_GET 0x09
+
+#define SXEVF_REDIR_TBL_GET 0x0a
+#define SXEVF_RSS_KEY_GET 0x0b
+#define SXEVF_CAST_MODE_SET 0x0c
+#define SXEVF_LINK_ENABLE_GET 0X0d
+#define SXEVF_IPSEC_ADD 0x0e
+#define SXEVF_IPSEC_DEL 0x0f
+#define SXEVF_RSS_CONF_GET 0x10
+
+#define SXEVF_PF_CTRL_MSG_LINK_UPDATE 0x100
+#define SXEVF_PF_CTRL_MSG_NETDEV_DOWN 0x200
+
+#define SXEVF_PF_CTRL_MSG_REINIT 0x400
+
+#define SXEVF_PF_CTRL_MSG_MASK 0x700
+#define SXEVF_PFREQ_MASK 0xFF00
+
+#define SXEVF_RSS_HASH_KEY_SIZE (40)
+#define SXEVF_MAX_RETA_ENTRIES (128)
+#define SXEVF_RETA_ENTRIES_DWORDS (SXEVF_MAX_RETA_ENTRIES / 16)
+
+#define SXEVF_TX_QUEUES 1
+#define SXEVF_RX_QUEUES 2
+#define SXEVF_TRANS_VLAN 3
+#define SXEVF_DEF_QUEUE 4
+
+#define SXEVF_MSGTYPE_ACK 0x80000000
+#define SXEVF_MSGTYPE_NACK 0x40000000
+
+#define SXEVF_MSGINFO_SHIFT 16
+#define SXEVF_MSGINFO_MASK (0xFF << SXEVF_MSGINFO_SHIFT)
+
+#define SXEVF_MSG_NUM(size) DIV_ROUND_UP(size, 4)
+
+enum sxevf_mbx_api_version {
+ SXEVF_MBX_API_10 = 0,
+ SXEVF_MBX_API_11,
+ SXEVF_MBX_API_12,
+ SXEVF_MBX_API_13,
+ SXEVF_MBX_API_14,
+
+ SXEVF_MBX_API_NR,
+};
+
+enum sxevf_cast_mode {
+ SXEVF_CAST_MODE_NONE = 0,
+ SXEVF_CAST_MODE_MULTI,
+ SXEVF_CAST_MODE_ALLMULTI,
+ SXEVF_CAST_MODE_PROMISC,
+};
+
+struct sxevf_rst_msg {
+ u32 msg_type;
+ u32 mac_addr[2];
+ u32 mc_fiter_type;
+};
+
+struct sxevf_mbx_api_msg {
+ u32 msg_type;
+ u32 api_version;
+};
+
+struct sxevf_ring_info_msg {
+ u32 msg_type;
+ u8 max_rx_num;
+ u8 max_tx_num;
+ u8 tc_num;
+ u8 default_tc;
+};
+
+struct sxevf_uc_addr_msg {
+ u32 msg_type;
+ u8 uc_addr[SXEVF_MAC_ADDR_LEN];
+ u16 pad;
+};
+
+struct sxevf_cast_mode_msg {
+ u32 msg_type;
+ u32 cast_mode;
+};
+
+struct sxevf_mc_sync_msg {
+ u16 msg_type;
+ u16 mc_cnt;
+ u16 mc_addr_extract[SXEVF_MC_ENTRY_NUM_MAX];
+};
+
+struct sxevf_uc_sync_msg {
+ u16 msg_type;
+ u16 index;
+ u32 addr[2];
+};
+
+struct sxevf_max_frame_msg {
+ u32 msg_type;
+ u32 max_frame;
+};
+
+struct sxevf_vlan_filter_msg {
+ u32 msg_type;
+ u32 vlan_id;
+};
+
+struct sxevf_redir_tbl_msg {
+ u32 type;
+ u32 entries[SXEVF_RETA_ENTRIES_DWORDS];
+};
+
+struct sxevf_rss_hsah_key_msg {
+ u32 type;
+ u8 hash_key[SXEVF_RSS_HASH_KEY_SIZE];
+};
+
+struct sxevf_rss_hash_msg {
+ u32 msg_type;
+ u8 hash_key[SXEVF_RSS_HASH_KEY_SIZE];
+ u64 rss_hf;
+};
+
+struct sxevf_ipsec_add_msg {
+ u32 msg_type;
+ u32 pf_sa_idx;
+ __be32 spi;
+ u8 flags;
+ u8 proto;
+ u16 family;
+ __be32 addr[4];
+ u32 key[5];
+};
+
+struct sxevf_ipsec_del_msg {
+ u32 msg_type;
+ u32 sa_idx;
+};
+
+void sxevf_mbx_init(struct sxevf_hw *hw);
+
+void sxevf_mbx_api_version_init(struct sxevf_adapter *adapter);
+
+bool sxevf_pf_rst_check(struct sxevf_hw *hw);
+
+s32 sxevf_mbx_msg_rcv(struct sxevf_hw *hw, u32 *msg, u16 msg_len);
+
+s32 sxevf_send_and_rcv_msg(struct sxevf_hw *hw, u32 *msg, u8 msg_len);
+
+s32 sxevf_mac_addr_set(struct sxevf_hw *hw, u8 *uc_addr);
+
+s32 sxevf_ring_info_get(struct sxevf_adapter *adapter,
+ u8 *tc_num, u8 *default_tc);
+
+s32 sxevf_rss_hash_config_get(struct sxevf_adapter *adapter,
+ struct rte_eth_rss_conf *rss_conf);
+
+void sxevf_mbx_api_version_init(struct sxevf_adapter *adapter);
+
+s32 sxevf_ctrl_msg_rcv(struct sxevf_hw *hw, u32 *msg, u16 msg_len);
+
+s32 sxevf_rx_max_frame_set(struct sxevf_hw *hw, u32 mtu);
+
+s32 sxevf_vlan_id_set(struct sxevf_hw *hw, u32 vlan,
+ bool vlan_on);
+s32 sxevf_cast_mode_set(struct sxevf_hw *hw, enum sxevf_cast_mode mode);
+
+s32 sxevf_uc_addr_add(struct sxevf_hw *hw, u32 index, u8 *mac_addr);
+
+s32 sxevf_ctrl_msg_rcv_and_clear(struct sxevf_hw *hw, u32 *msg, u16 msg_len);
+
+#endif
diff --git a/drivers/net/sxe/vf/sxevf_offload.c b/drivers/net/sxe/vf/sxevf_offload.c
new file mode 100644
index 0000000000..4b0eacf7f0
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_offload.c
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+#include "sxe_dpdk_version.h"
+#include <ethdev_driver.h>
+
+#include "sxe_types.h"
+#include "sxe_offload_common.h"
+#include "sxevf_offload.h"
+
+u64 sxevf_rx_queue_offloads_get(struct rte_eth_dev *dev)
+{
+ return __sxe_rx_queue_offload_capa_get(dev);
+}
+
+u64 sxevf_rx_port_offloads_get(struct rte_eth_dev *dev)
+{
+ return __sxe_rx_port_offload_capa_get(dev);
+}
+
+u64 sxevf_tx_queue_offloads_get(struct rte_eth_dev *dev)
+{
+ RTE_SET_USED(dev);
+
+ return 0;
+}
+
+u64 sxevf_tx_port_offloads_get(struct rte_eth_dev *dev)
+{
+ return __sxe_tx_port_offload_capa_get(dev);
+}
diff --git a/drivers/net/sxe/vf/sxevf_offload.h b/drivers/net/sxe/vf/sxevf_offload.h
new file mode 100644
index 0000000000..ae4bf87f30
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_offload.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#ifndef __SXEVF_OFFLOAD_H__
+#define __SXEVF_OFFLOAD_H__
+
+u64 sxevf_rx_queue_offloads_get(struct rte_eth_dev *dev);
+
+u64 sxevf_rx_port_offloads_get(struct rte_eth_dev *dev);
+
+u64 sxevf_tx_queue_offloads_get(struct rte_eth_dev *dev);
+
+u64 sxevf_tx_port_offloads_get(struct rte_eth_dev *dev);
+
+#endif
diff --git a/drivers/net/sxe/vf/sxevf_queue.c b/drivers/net/sxe/vf/sxevf_queue.c
new file mode 100644
index 0000000000..4461d13369
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_queue.c
@@ -0,0 +1,210 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#if defined SXE_DPDK_L4_FEATURES && defined SXE_DPDK_SRIOV
+
+#include <rte_byteorder.h>
+#include <rte_mbuf_core.h>
+#include <rte_ethdev.h>
+
+#include "sxe_dpdk_version.h"
+#include "sxevf_rx.h"
+#include "sxevf_tx.h"
+#include "sxe_logs.h"
+#include "sxevf.h"
+#include "sxe_queue_common.h"
+#include "sxevf_hw.h"
+#include "sxe_offload.h"
+#include "sxe_ethdev.h"
+#include "sxevf_queue.h"
+#include "sxevf_msg.h"
+
+s32 __rte_cold sxevf_rx_queue_mbufs_alloc(sxevf_rx_queue_s *rxq)
+{
+ s32 ret;
+
+ ret = __sxe_rx_queue_mbufs_alloc((sxevf_rx_queue_s *)rxq);
+
+ return ret;
+}
+
+s32 __rte_cold sxevf_rx_queue_setup(struct rte_eth_dev *dev,
+ u16 queue_idx, u16 desc_num,
+ unsigned int socket_id,
+ const struct rte_eth_rxconf *rx_conf,
+ struct rte_mempool *mp)
+{
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ struct rx_setup rx_setup = {};
+ s32 ret;
+
+ PMD_INIT_FUNC_TRACE();
+
+ rx_setup.desc_num = desc_num;
+ rx_setup.queue_idx = queue_idx;
+ rx_setup.socket_id = socket_id;
+ rx_setup.mp = mp;
+ rx_setup.dev = dev;
+ rx_setup.reg_base_addr = hw->reg_base_addr;
+ rx_setup.rx_conf = rx_conf;
+ rx_setup.rx_batch_alloc_allowed = &adapter->rx_batch_alloc_allowed;
+
+ ret = __sxe_rx_queue_setup(&rx_setup, true);
+ if (ret)
+ LOG_ERROR_BDF("rx queue setup fail.(err:%d)", ret);
+
+ return ret;
+}
+
+s32 __rte_cold sxevf_tx_queue_setup(struct rte_eth_dev *dev,
+ u16 tx_queue_id,
+ u16 ring_depth,
+ u32 socket_id,
+ const struct rte_eth_txconf *tx_conf)
+{
+ s32 ret;
+ struct sxevf_hw *hw = (&((struct sxevf_adapter *)(dev->data->dev_private))->hw);
+ struct tx_setup tx_setup;
+
+ tx_setup.dev = dev;
+ tx_setup.desc_num = ring_depth;
+ tx_setup.queue_idx = tx_queue_id;
+ tx_setup.socket_id = socket_id;
+ tx_setup.reg_base_addr = hw->reg_base_addr;
+ tx_setup.tx_conf = tx_conf;
+
+ ret = __sxe_tx_queue_setup(&tx_setup, true);
+ if (ret)
+ PMD_LOG_ERR(DRV, "rx queue setup fail.(err:%d)", ret);
+
+ return ret;
+}
+
+void __rte_cold
+sxevf_rx_queue_release(struct rte_eth_dev *dev, u16 queue_id)
+{
+ __sxe_rx_queue_free(dev->data->rx_queues[queue_id]);
+}
+
+void __rte_cold
+sxevf_tx_queue_release(struct rte_eth_dev *dev, u16 queue_id)
+{
+ __sxe_tx_queue_free(dev->data->tx_queues[queue_id]);
+}
+
+void sxevf_rx_queue_info_get(struct rte_eth_dev *dev, u16 queue_id,
+ struct rte_eth_rxq_info *qinfo)
+{
+ __sxe_rx_queue_info_get(dev, queue_id, qinfo);
+}
+
+void sxevf_tx_queue_info_get(struct rte_eth_dev *dev, u16 queue_id,
+ struct rte_eth_txq_info *q_info)
+{
+ __sxe_tx_queue_info_get(dev, queue_id, q_info);
+}
+
+s32 sxevf_tx_done_cleanup(void *tx_queue, u32 free_cnt)
+{
+ s32 ret;
+
+ /* Tx queue cleanup */
+ ret = __sxe_tx_done_cleanup(tx_queue, free_cnt);
+ if (ret)
+ PMD_LOG_ERR(DRV, "tx cleanup fail.(err:%d)", ret);
+
+ return ret;
+}
+
+s32 sxevf_rss_reta_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ u16 reta_size)
+{
+ s32 ret = -ENOTSUP;
+
+ PMD_INIT_FUNC_TRACE();
+
+ RTE_SET_USED(reta_conf);
+ RTE_SET_USED(reta_size);
+
+ if (!dev->data->dev_started) {
+ PMD_LOG_ERR(DRV,
+ "port %d must be started before rss reta update",
+ dev->data->port_id);
+ ret = -EIO;
+ goto l_out;
+ }
+
+ PMD_LOG_ERR(DRV, "rss reta update is not supported on vf.(err:%d)", ret);
+
+l_out:
+ return ret;
+}
+
+s32 sxevf_rss_reta_query(struct rte_eth_dev *dev,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ u16 reta_size)
+{
+ s32 ret = 0;
+
+ RTE_SET_USED(dev);
+ RTE_SET_USED(reta_conf);
+
+ if (reta_size != 0) {
+ ret = -EINVAL;
+ PMD_LOG_ERR(DRV, "vf rss reta size:0, not support query.(err:%d)", ret);
+ }
+
+ return ret;
+}
+
+s32 sxevf_rss_hash_conf_get(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf)
+{
+ s32 ret = 0;
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+
+ ret = sxevf_rss_hash_config_get(adapter, rss_conf);
+ if (ret) {
+ LOG_ERROR_BDF("rss hash config get failed.(err:%d)", ret);
+ goto l_out;
+ }
+
+l_out:
+ return ret;
+}
+
+s32 sxevf_rss_hash_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf)
+{
+ s32 ret = -ENOTSUP;
+
+ RTE_SET_USED(dev);
+ RTE_SET_USED(rss_conf);
+
+ PMD_LOG_ERR(DRV, "rss hash update is not supported on vf.(err:%d)", ret);
+
+ return ret;
+}
+
+void sxevf_secondary_proc_init(struct rte_eth_dev *eth_dev)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ bool rx_vec_allowed = 0;
+
+ __sxe_secondary_proc_init(eth_dev, adapter->rx_batch_alloc_allowed, &rx_vec_allowed);
+}
+
+void __rte_cold sxevf_txrx_queues_clear(struct rte_eth_dev *dev, bool rx_batch_alloc_allowed)
+{
+ __sxe_txrx_queues_clear(dev, rx_batch_alloc_allowed);
+}
+
+void sxevf_queues_free(struct rte_eth_dev *dev)
+{
+ __sxe_queues_free(dev);
+}
+
+#endif
diff --git a/drivers/net/sxe/vf/sxevf_queue.h b/drivers/net/sxe/vf/sxevf_queue.h
new file mode 100644
index 0000000000..9407e941fb
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_queue.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#ifndef __SXEVF_QUEUEU_H__
+#define __SXEVF_QUEUEU_H__
+
+#include "sxe_dpdk_version.h"
+#include "sxe_types.h"
+#include "sxe_queue_common.h"
+
+typedef union sxe_tx_data_desc sxevf_tx_data_desc_u;
+typedef struct sxe_rx_buffer sxevf_rx_buffer_s;
+typedef union sxe_rx_data_desc sxevf_rx_data_desc_u;
+typedef struct sxe_tx_queue sxevf_tx_queue_s;
+typedef struct sxe_rx_queue sxevf_rx_queue_s;
+
+s32 __rte_cold sxevf_rx_queue_mbufs_alloc(sxevf_rx_queue_s *rxq);
+
+s32 __rte_cold sxevf_rx_queue_setup(struct rte_eth_dev *dev,
+ u16 queue_idx, u16 desc_num,
+ unsigned int socket_id,
+ const struct rte_eth_rxconf *rx_conf,
+ struct rte_mempool *mp);
+
+s32 __rte_cold sxevf_tx_queue_setup(struct rte_eth_dev *dev,
+ u16 tx_queue_id,
+ u16 ring_depth,
+ u32 socket_id,
+ const struct rte_eth_txconf *tx_conf);
+void __rte_cold sxevf_tx_queue_release(struct rte_eth_dev *dev, u16 queue_id);
+
+void __rte_cold sxevf_rx_queue_release(struct rte_eth_dev *dev, u16 queue_id);
+
+void sxevf_rx_queue_info_get(struct rte_eth_dev *dev, u16 queue_id,
+ struct rte_eth_rxq_info *qinfo);
+
+void sxevf_tx_queue_info_get(struct rte_eth_dev *dev, u16 queue_id,
+ struct rte_eth_txq_info *q_info);
+
+s32 sxevf_tx_done_cleanup(void *tx_queue, u32 free_cnt);
+
+s32 sxevf_rss_reta_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ u16 reta_size);
+
+s32 sxevf_rss_reta_query(struct rte_eth_dev *dev,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ u16 reta_size);
+
+s32 sxevf_rss_hash_conf_get(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf);
+
+s32 sxevf_rss_hash_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf);
+
+void sxevf_secondary_proc_init(struct rte_eth_dev *eth_dev);
+
+s32 sxevf_rx_descriptor_status(void *rx_queue, u16 offset);
+
+u16 sxevf_pkts_recv(void *rx_queue, struct rte_mbuf **rx_pkts, u16 num_pkts);
+
+u16 sxevf_pkts_xmit_with_offload(void *tx_queue, struct rte_mbuf **tx_pkts, u16 pkts_num);
+s32 sxevf_tx_descriptor_status(void *tx_queue, u16 offset);
+
+void __rte_cold sxevf_txrx_queues_clear(struct rte_eth_dev *dev, bool rx_batch_alloc_allowed);
+
+void sxevf_queues_free(struct rte_eth_dev *dev);
+
+#endif
diff --git a/drivers/net/sxe/vf/sxevf_rx.c b/drivers/net/sxe/vf/sxevf_rx.c
new file mode 100644
index 0000000000..aee63d025d
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_rx.c
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#if defined SXE_DPDK_L4_FEATURES && defined SXE_DPDK_SRIOV
+
+#include <rte_common.h>
+#include "sxe_dpdk_version.h"
+#include <ethdev_driver.h>
+
+#include "sxe_logs.h"
+#include "sxe_errno.h"
+#include "sxevf.h"
+#include "sxevf_msg.h"
+#include "sxevf_rx.h"
+#include "sxe_rx_common.h"
+#include "sxevf_queue.h"
+#include "sxevf_rx.h"
+#include "sxe_ethdev.h"
+
+#define SXEVF_RX_HDR_SIZE 256
+
+static void sxevf_rss_bit_num_configure(struct sxevf_hw *hw, u16 rx_queues_num)
+{
+ u32 psrtype;
+
+ psrtype = (rx_queues_num >> 1) << SXEVF_PSRTYPE_RQPL_SHIFT;
+
+ sxevf_rss_bit_num_set(hw, psrtype);
+}
+
+static void sxevf_rxmode_offload_configure(struct rte_eth_dev *eth_dev,
+ u64 queue_offload, u32 buf_size)
+{
+ struct rte_eth_rxmode *rxmode = ð_dev->data->dev_conf.rxmode;
+ u32 frame_size = SXE_GET_FRAME_SIZE(eth_dev);
+
+ if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_SCATTER ||
+ ((frame_size + 2 * SXEVF_VLAN_TAG_SIZE) > buf_size)) {
+ if (!eth_dev->data->scattered_rx) {
+ PMD_LOG_WARN(DRV, "rxmode offload:0x%" SXE_PRIX64 " max_rx_pkt_len:%u "
+ "buf_size:%u enable rx scatter",
+ rxmode->offloads,
+ frame_size,
+ buf_size);
+ }
+ eth_dev->data->scattered_rx = 1;
+ }
+
+ if (queue_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
+ rxmode->offloads |= RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
+}
+
+static s32 sxevf_rx_queue_configure(struct rte_eth_dev *eth_dev)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ sxevf_rx_queue_s *rxq;
+ struct rte_eth_rxmode *rxmode = ð_dev->data->dev_conf.rxmode;
+ s32 ret;
+ u16 i;
+ u32 len;
+ u32 buf_size;
+
+ rxmode->offloads &= ~RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
+ for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
+ rxq = eth_dev->data->rx_queues[i];
+ len = rxq->ring_depth * sizeof(sxevf_rx_data_desc_u);
+
+ ret = sxevf_rx_queue_mbufs_alloc(rxq);
+ if (ret) {
+ LOG_ERROR_BDF("rx queue num:%u queue id:%u alloc "
+ "rx buffer fail.(err:%d)",
+ eth_dev->data->nb_rx_queues, i, ret);
+ goto l_out;
+ }
+
+ buf_size = (u16)(rte_pktmbuf_data_room_size(rxq->mb_pool) -
+ RTE_PKTMBUF_HEADROOM);
+
+ sxevf_rx_ring_desc_configure(hw, len, rxq->base_addr, rxq->reg_idx);
+
+ sxevf_rx_rcv_ctl_configure(hw, rxq->reg_idx, SXEVF_RX_HDR_SIZE,
+ buf_size, rxq->drop_en);
+
+ sxevf_rxmode_offload_configure(eth_dev, rxq->offloads, buf_size);
+ }
+
+ sxevf_rss_bit_num_configure(hw, eth_dev->data->nb_rx_queues);
+
+ sxevf_rx_function_set(eth_dev);
+
+l_out:
+ return ret;
+}
+
+s32 sxevf_rx_configure(struct rte_eth_dev *eth_dev)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ u32 frame_size = SXE_GET_FRAME_SIZE(eth_dev);
+ u32 mtu = frame_size - SXE_ETH_OVERHEAD;
+ s32 ret;
+
+ if (rte_is_power_of_2(eth_dev->data->nb_rx_queues) == 0) {
+ ret = -SXEVF_ERR_PARAM;
+ LOG_ERROR_BDF("invalid rx queue num:%u.",
+ eth_dev->data->nb_rx_queues);
+ goto l_out;
+ }
+
+ if (eth_dev->data->nb_rx_queues > adapter->max_rx_queue) {
+ ret = -SXEVF_ERR_PARAM;
+ LOG_ERROR_BDF("invalid rx queue num:%u exceed max rx queue:%u ",
+ eth_dev->data->nb_rx_queues,
+ adapter->max_rx_queue);
+ goto l_out;
+ }
+
+ ret = sxevf_rx_max_frame_set(hw, mtu);
+ if (ret) {
+ LOG_ERROR_BDF("max frame size:%u set fail.(err:%d)",
+ frame_size, ret);
+ goto l_out;
+ }
+
+ ret = sxevf_rx_queue_configure(eth_dev);
+ if (ret) {
+ LOG_ERROR_BDF("rx queue num:%u configure fail.(err:%u)",
+ eth_dev->data->nb_rx_queues, ret);
+ }
+
+l_out:
+ return ret;
+}
+
+void __rte_cold sxevf_rx_function_set(struct rte_eth_dev *dev)
+{
+ struct sxevf_adapter *adapter = dev->data->dev_private;
+
+#if defined SXE_DPDK_L4_FEATURES && defined SXE_DPDK_SIMD
+ __sxe_rx_function_set(dev, adapter->rx_batch_alloc_allowed, &adapter->rx_vec_allowed);
+#else
+ __sxe_rx_function_set(dev, adapter->rx_batch_alloc_allowed, NULL);
+#endif
+}
+
+s32 sxevf_rx_descriptor_status(void *rx_queue, u16 offset)
+{
+ return __sxe_rx_descriptor_status(rx_queue, offset);
+}
+
+u16 sxevf_pkts_recv(void *rx_queue, struct rte_mbuf **rx_pkts, u16 num_pkts)
+{
+ return __sxe_pkts_recv(rx_queue, rx_pkts, num_pkts);
+}
+
+const u32 *sxevf_dev_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements)
+{
+ return __sxe_dev_supported_ptypes_get(dev, no_of_elements);
+}
+
+#endif
diff --git a/drivers/net/sxe/vf/sxevf_rx.h b/drivers/net/sxe/vf/sxevf_rx.h
new file mode 100644
index 0000000000..55ca2705c1
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_rx.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#ifndef __SXEVF_RX_H__
+#define __SXEVF_RX_H__
+
+#include "sxe_queue_common.h"
+
+#define SXEVF_RX_DESC_RING_ALIGN (SXE_ALIGN / sizeof(sxevf_rx_data_desc_t))
+
+s32 sxevf_rx_configure(struct rte_eth_dev *eth_dev);
+
+const u32 *sxevf_dev_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements);
+
+void __rte_cold sxevf_rx_function_set(struct rte_eth_dev *dev);
+
+#endif
diff --git a/drivers/net/sxe/vf/sxevf_stats.c b/drivers/net/sxe/vf/sxevf_stats.c
new file mode 100644
index 0000000000..21407dac42
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_stats.c
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#if defined SXE_DPDK_L4_FEATURES && defined SXE_DPDK_SRIOV
+
+#include <rte_ethdev.h>
+
+#include "sxevf_stats.h"
+#include "sxe_logs.h"
+#include "sxe_errno.h"
+#include "sxevf.h"
+
+#define SXE_HW_XSTATS_CNT (sizeof(sxevf_xstats_field) / \
+ sizeof(sxevf_xstats_field[0]))
+
+static const struct sxevf_stats_field sxevf_xstats_field[] = {
+ {"rx_multicast_packets", offsetof(struct sxevf_hw_stats, vfmprc)},
+};
+
+#ifdef SXE_TEST
+static u32 sxevf_xstats_cnt_get(void)
+{
+ return SXE_HW_XSTATS_CNT;
+}
+#endif
+
+s32 sxevf_eth_stats_get(struct rte_eth_dev *eth_dev,
+ struct rte_eth_stats *stats)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_stats_info *stats_info = &adapter->stats_info;
+ struct sxevf_hw *hw = &adapter->hw;
+ s32 ret = 0;
+
+ sxevf_packet_stats_get(hw, &stats_info->hw_stats);
+
+ if (stats == NULL) {
+ ret = -EINVAL;
+ PMD_LOG_ERR(DRV, "input param stats is null.");
+ goto l_out;
+ }
+
+ stats->ipackets = stats_info->hw_stats.vfgprc;
+ stats->ibytes = stats_info->hw_stats.vfgorc;
+ stats->opackets = stats_info->hw_stats.vfgptc;
+ stats->obytes = stats_info->hw_stats.vfgotc - stats->opackets * RTE_ETHER_CRC_LEN;
+
+l_out:
+ return ret;
+}
+
+s32 sxevf_dev_stats_reset(struct rte_eth_dev *eth_dev)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_stats_info *stats_info = &adapter->stats_info;
+
+ sxevf_eth_stats_get(eth_dev, NULL);
+
+ stats_info->hw_stats.vfgprc = 0;
+ stats_info->hw_stats.vfgorc = 0;
+ stats_info->hw_stats.vfgptc = 0;
+ stats_info->hw_stats.vfgotc = 0;
+ stats_info->hw_stats.vfmprc = 0;
+
+ return 0;
+}
+
+static s32 sxevf_hw_xstat_offset_get(u32 id, u32 *offset)
+{
+ s32 ret = 0;
+ u32 size = SXE_HW_XSTATS_CNT;
+
+ if (id < size) {
+ *offset = sxevf_xstats_field[id].offset;
+ } else {
+ ret = -SXE_ERR_PARAM;
+ PMD_LOG_ERR(DRV, "invalid id:%u exceed stats size cnt:%u.",
+ id, size);
+ }
+
+ return ret;
+}
+
+s32 sxevf_xstats_get(struct rte_eth_dev *eth_dev,
+ struct rte_eth_xstat *xstats,
+ u32 usr_cnt)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_stats_info *stats_info = &adapter->stats_info;
+ struct sxevf_hw *hw = &adapter->hw;
+ u32 i;
+ u32 cnt;
+ s32 ret;
+ u32 offset;
+
+ cnt = SXE_HW_XSTATS_CNT;
+ PMD_LOG_INFO(DRV, "xstat size:%u. hw xstat field cnt:%" SXE_PRIU64,
+ cnt,
+ SXE_HW_XSTATS_CNT);
+
+ if (usr_cnt < cnt) {
+ ret = cnt;
+ PMD_LOG_ERR(DRV, "user usr_cnt:%u less than stats cnt:%u.",
+ usr_cnt, cnt);
+ goto l_out;
+ }
+
+ sxevf_packet_stats_get(hw, &stats_info->hw_stats);
+
+ if (xstats == NULL) {
+ ret = 0;
+ PMD_LOG_ERR(DRV, "usr_cnt:%u, input param xstats is null.",
+ usr_cnt);
+ goto l_out;
+ }
+
+ cnt = 0;
+ for (i = 0; i < SXE_HW_XSTATS_CNT; i++) {
+ sxevf_hw_xstat_offset_get(i, &offset);
+ xstats[cnt].value = *(ulong *)(((s8 *)(&stats_info->hw_stats)) + offset);
+ xstats[cnt].id = cnt;
+ cnt++;
+ }
+
+ ret = SXE_HW_XSTATS_CNT;
+
+l_out:
+ return ret;
+}
+
+s32 sxevf_xstats_names_get(__rte_unused struct rte_eth_dev *dev,
+ struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned int usr_cnt)
+{
+ u32 i = 0;
+ u32 cnt = 0;
+ s32 ret;
+
+ if (xstats_names == NULL) {
+ ret = SXE_HW_XSTATS_CNT;
+ PMD_LOG_INFO(DRV, "xstats field size:%u.", ret);
+ goto l_out;
+ } else if (usr_cnt < SXE_HW_XSTATS_CNT) {
+ ret = -ENOMEM;
+ PMD_LOG_ERR(DRV, "usr_cnt:%u invalid.(err:%d).", usr_cnt, ret);
+ goto l_out;
+ }
+
+ for (i = 0; i < SXE_HW_XSTATS_CNT; i++) {
+ strlcpy(xstats_names[cnt].name,
+ sxevf_xstats_field[i].name,
+ sizeof(xstats_names[cnt].name));
+ cnt++;
+ }
+
+ ret = cnt;
+
+l_out:
+ return ret;
+}
+
+#endif
diff --git a/drivers/net/sxe/vf/sxevf_stats.h b/drivers/net/sxe/vf/sxevf_stats.h
new file mode 100644
index 0000000000..ddf56c39df
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_stats.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#ifndef __SXEVF_STATS_H__
+#define __SXEVF_STATS_H__
+
+#include "sxevf_hw.h"
+
+struct sxevf_stats_field {
+ s8 name[RTE_ETH_XSTATS_NAME_SIZE];
+ u32 offset;
+};
+
+struct sxevf_stats_info {
+ struct sxevf_hw_stats hw_stats;
+};
+
+s32 sxevf_eth_stats_get(struct rte_eth_dev *eth_dev,
+ struct rte_eth_stats *stats);
+
+s32 sxevf_dev_stats_reset(struct rte_eth_dev *eth_dev);
+
+s32 sxevf_xstats_get(struct rte_eth_dev *eth_dev,
+ struct rte_eth_xstat *xstats,
+ u32 usr_cnt);
+
+s32 sxevf_xstats_names_get(__rte_unused struct rte_eth_dev *dev,
+ struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned int usr_cnt);
+
+#endif
diff --git a/drivers/net/sxe/vf/sxevf_tx.c b/drivers/net/sxe/vf/sxevf_tx.c
new file mode 100644
index 0000000000..099f737e9a
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_tx.c
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#if defined SXE_DPDK_L4_FEATURES && defined SXE_DPDK_SRIOV
+
+#include <rte_ethdev.h>
+
+#include "sxe_logs.h"
+#include "sxevf.h"
+#include "sxevf_tx.h"
+#include "sxevf_queue.h"
+#include "sxe_tx_common.h"
+
+void sxevf_tx_configure(struct rte_eth_dev *eth_dev)
+{
+ struct sxevf_adapter *adapter = eth_dev->data->dev_private;
+ struct sxevf_hw *hw = &adapter->hw;
+ sxevf_tx_queue_s *txq;
+ u16 i;
+ u32 len;
+
+ for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
+ txq = eth_dev->data->tx_queues[i];
+ len = txq->ring_depth * sizeof(sxevf_tx_data_desc_u);
+ sxevf_tx_desc_configure(hw, len, txq->base_addr, txq->reg_idx);
+
+ sxevf_tx_queue_thresh_set(hw, txq->reg_idx,
+ txq->pthresh, txq->hthresh, txq->wthresh);
+ }
+
+ LOG_DEBUG_BDF("tx queue num:%u tx configure done.",
+ eth_dev->data->nb_tx_queues);
+}
+
+s32 sxevf_tx_descriptor_status(void *tx_queue, u16 offset)
+{
+ return __sxe_tx_descriptor_status(tx_queue, offset);
+}
+
+u16 sxevf_pkts_xmit_with_offload(void *tx_queue, struct rte_mbuf **tx_pkts, u16 pkts_num)
+{
+ return __sxe_pkts_xmit_with_offload(tx_queue, tx_pkts, pkts_num);
+}
+
+#endif
diff --git a/drivers/net/sxe/vf/sxevf_tx.h b/drivers/net/sxe/vf/sxevf_tx.h
new file mode 100644
index 0000000000..c8ad400bca
--- /dev/null
+++ b/drivers/net/sxe/vf/sxevf_tx.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C), 2022, Linkdata Technology Co., Ltd.
+ */
+
+#ifndef __SXEVF_TX_H__
+#define __SXEVF_TX_H__
+
+#include "sxe_queue_common.h"
+
+#define SXEVF_TX_DESC_RING_ALIGN (SXE_ALIGN / sizeof(sxevf_tx_data_desc_u))
+
+void sxevf_tx_configure(struct rte_eth_dev *eth_dev);
+
+#endif
--
2.18.4
next prev parent reply other threads:[~2025-07-19 9:07 UTC|newest]
Thread overview: 338+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-25 2:36 [PATCH 01/13] net/sxe: add base driver directory and doc Jie Liu
2025-04-25 2:36 ` [PATCH 02/13] net/sxe: add ethdev probe and remove Jie Liu
2025-04-26 16:11 ` Stephen Hemminger
2025-04-26 16:11 ` Stephen Hemminger
2025-04-26 16:15 ` Stephen Hemminger
2025-04-26 16:17 ` Stephen Hemminger
2025-04-25 2:36 ` [PATCH 03/13] net/sxe: add tx rx setup and data path Jie Liu
2025-04-26 16:02 ` Stephen Hemminger
2025-04-26 16:20 ` Stephen Hemminger
2025-04-25 2:36 ` [PATCH 04/13] net/sxe: add link, flow ctrl, mac ops, mtu ops function Jie Liu
2025-04-25 2:36 ` [PATCH 05/13] net/sxe: support vlan filter Jie Liu
2025-04-25 2:36 ` [PATCH 06/13] net/sxe: add mac layer filter function Jie Liu
2025-04-25 2:36 ` [PATCH 07/13] net/sxe: support rss offload Jie Liu
2025-04-25 2:36 ` [PATCH 08/13] net/sxe: add dcb function Jie Liu
2025-04-25 2:36 ` [PATCH 09/13] net/sxe: support ptp Jie Liu
2025-04-25 2:36 ` [PATCH 10/13] net/sxe: add xstats function Jie Liu
2025-04-25 2:36 ` [PATCH 11/13] net/sxe: add custom cmd led ctrl Jie Liu
2025-04-25 2:36 ` [PATCH 12/13] net/sxe: add simd function Jie Liu
2025-04-25 2:36 ` [PATCH 13/13] net/sxe: add virtual function Jie Liu
2025-04-26 15:57 ` [PATCH 01/13] net/sxe: add base driver directory and doc Stephen Hemminger
2025-04-26 15:59 ` Stephen Hemminger
2025-04-26 16:23 ` Stephen Hemminger
2025-04-26 17:07 ` Stephen Hemminger
2025-04-26 17:08 ` Stephen Hemminger
2025-07-04 2:53 ` [PATCH v2 01/14] net/sxe: add base driver directory and doc Adding a minimum maintainable directory structure for the network driver and request maintenance of the sxe driver Jie Liu
2025-07-07 11:58 ` [PATCH v3 01/14] net/sxe: add base driver directory and doc Jie Liu
2025-07-07 11:58 ` [PATCH v3 02/14] net/sxe: add ethdev probe and remove Jie Liu
2025-07-07 14:57 ` Stephen Hemminger
2025-07-07 11:58 ` [PATCH v3 03/14] net/sxe: add tx rx setup and data path Jie Liu
2025-07-07 11:58 ` [PATCH v3 04/14] net/sxe: add link, flow ctrl, mac ops, mtu ops function Jie Liu
2025-07-07 11:58 ` [PATCH v3 05/14] net/sxe: support vlan filter Jie Liu
2025-07-07 11:58 ` [PATCH v3 06/14] net/sxe: add filter function Jie Liu
2025-07-07 11:58 ` [PATCH v3 07/14] net/sxe: support rss offload Jie Liu
2025-07-07 11:58 ` [PATCH v3 08/14] net/sxe: add dcb function Jie Liu
2025-07-07 11:58 ` [PATCH v3 09/14] net/sxe: support ptp Jie Liu
2025-07-07 11:58 ` [PATCH v3 10/14] net/sxe: add xstats function Jie Liu
2025-07-07 11:58 ` [PATCH v3 11/14] net/sxe: add custom cmd led ctrl Jie Liu
2025-07-07 11:58 ` [PATCH v3 12/14] net/sxe: add simd function Jie Liu
2025-07-07 11:58 ` [PATCH v3 13/14] net/sxe: add virtual function Jie Liu
2025-07-07 11:58 ` [PATCH v3 14/14] net/sxe: add Solve compilation problems Jie Liu
2025-07-07 15:03 ` Stephen Hemminger
2025-07-07 15:56 ` Stephen Hemminger
2025-07-09 8:43 ` [PATCH v4 1/2] net/sxe: add base driver directory and doc Jie Liu
2025-07-09 8:43 ` [PATCH v4 2/2] net/sxe: add ethdev probe and remove Jie Liu
2025-07-09 16:13 ` Stephen Hemminger
2025-07-09 8:43 ` [PATCH v4 03/14] net/sxe: add tx rx setup and data path Jie Liu
2025-07-09 16:07 ` Stephen Hemminger
2025-07-09 8:43 ` [PATCH v4 04/14] net/sxe: add link, flow ctrl, mac ops, mtu ops function Jie Liu
2025-07-09 16:09 ` Stephen Hemminger
2025-07-12 1:50 ` 刘洁
2025-07-09 16:11 ` Stephen Hemminger
2025-07-09 8:43 ` [PATCH v4 05/14] net/sxe: support vlan filter Jie Liu
2025-07-09 8:43 ` [PATCH v4 06/14] net/sxe: add filter function Jie Liu
2025-07-09 8:43 ` [PATCH v4 07/14] net/sxe: support rss offload Jie Liu
2025-07-09 8:43 ` [PATCH v4 08/14] net/sxe: add dcb function Jie Liu
2025-07-09 8:43 ` [PATCH v4 09/14] net/sxe: support ptp Jie Liu
2025-07-09 8:43 ` [PATCH v4 10/14] net/sxe: add xstats function Jie Liu
2025-07-09 8:43 ` [PATCH v4 11/14] net/sxe: add custom cmd led ctrl Jie Liu
2025-07-09 8:43 ` [PATCH v4 12/14] net/sxe: add simd function Jie Liu
2025-07-09 8:43 ` [PATCH v4 13/14] net/sxe: add virtual function Jie Liu
2025-07-09 8:43 ` [PATCH v4 14/14] net/sxe: add Solve compilation problems Jie Liu
2025-07-09 16:14 ` Stephen Hemminger
2025-07-10 1:20 ` [PATCH v5 01/14] net/sxe: add base driver directory and doc Jie Liu
2025-07-10 1:20 ` [PATCH v5 02/14] net/sxe: add ethdev probe and remove Jie Liu
2025-07-10 1:20 ` [PATCH v5 03/14] net/sxe: add tx rx setup and data path Jie Liu
2025-07-17 18:03 ` Stephen Hemminger
2025-07-17 18:05 ` Stephen Hemminger
2025-07-17 18:07 ` Stephen Hemminger
2025-07-17 18:09 ` Stephen Hemminger
2025-07-17 18:12 ` Stephen Hemminger
2025-07-10 1:20 ` [PATCH v5 04/14] net/sxe: add link, flow ctrl, mac ops, mtu ops function Jie Liu
2025-07-10 1:20 ` [PATCH v5 05/14] net/sxe: support vlan filter Jie Liu
2025-07-10 1:20 ` [PATCH v5 06/14] net/sxe: add filter function Jie Liu
2025-07-10 1:20 ` [PATCH v5 07/14] net/sxe: support rss offload Jie Liu
2025-07-10 1:20 ` [PATCH v5 08/14] net/sxe: add dcb function Jie Liu
2025-07-10 1:20 ` [PATCH v5 09/14] net/sxe: support ptp Jie Liu
2025-07-10 1:20 ` [PATCH v5 10/14] net/sxe: add xstats function Jie Liu
2025-07-10 1:20 ` [PATCH v5 11/14] net/sxe: add custom cmd led ctrl Jie Liu
2025-07-10 1:20 ` [PATCH v5 12/14] net/sxe: add simd function Jie Liu
2025-07-10 1:20 ` [PATCH v5 13/14] net/sxe: add virtual function Jie Liu
2025-07-10 1:20 ` [PATCH v5 14/14] net/sxe: add Solve compilation problems Jie Liu
2025-07-12 6:18 ` [PATCH v6 01/14] net/sxe: add base driver directory and doc Jie Liu
2025-07-12 6:18 ` [PATCH v6 02/14] net/sxe: add ethdev probe and remove Jie Liu
2025-07-12 6:18 ` [PATCH v6 03/14] net/sxe: add tx rx setup and data path Jie Liu
2025-07-12 6:18 ` [PATCH v6 04/14] net/sxe: add link, flow ctrl, mac ops, mtu ops function Jie Liu
2025-07-12 6:18 ` [PATCH v6 05/14] net/sxe: support vlan filter Jie Liu
2025-07-12 6:18 ` [PATCH v6 06/14] net/sxe: add filter function Jie Liu
2025-07-12 6:18 ` [PATCH v6 07/14] net/sxe: support rss offload Jie Liu
2025-07-12 6:18 ` [PATCH v6 08/14] net/sxe: add dcb function Jie Liu
2025-07-12 6:18 ` [PATCH v6 09/14] net/sxe: support ptp Jie Liu
2025-07-12 6:18 ` [PATCH v6 10/14] net/sxe: add xstats function Jie Liu
2025-07-12 6:18 ` [PATCH v6 11/14] net/sxe: add custom cmd led ctrl Jie Liu
2025-07-12 6:18 ` [PATCH v6 12/14] net/sxe: add simd function Jie Liu
2025-07-12 6:18 ` [PATCH v6 13/14] net/sxe: add virtual function Jie Liu
2025-07-12 6:18 ` [PATCH v6 14/14] net/sxe: add Solve compilation problems Jie Liu
2025-07-14 3:54 ` [PATCH v7 01/14] net/sxe: add base driver directory and doc Jie Liu
2025-07-14 3:54 ` [PATCH v7 02/14] net/sxe: add ethdev probe and remove Jie Liu
2025-07-14 3:54 ` [PATCH v7 03/14] net/sxe: add tx rx setup and data path Jie Liu
2025-07-14 3:54 ` [PATCH v7 04/14] net/sxe: add link, flow ctrl, mac ops, mtu ops function Jie Liu
2025-07-14 3:54 ` [PATCH v7 05/14] net/sxe: support vlan filter Jie Liu
2025-07-14 3:54 ` [PATCH v7 06/14] net/sxe: add filter function Jie Liu
2025-07-14 3:54 ` [PATCH v7 07/14] net/sxe: support rss offload Jie Liu
2025-07-14 3:54 ` [PATCH v7 08/14] net/sxe: add dcb function Jie Liu
2025-07-14 3:54 ` [PATCH v7 09/14] net/sxe: support ptp Jie Liu
2025-07-14 3:54 ` [PATCH v7 10/14] net/sxe: add xstats function Jie Liu
2025-07-14 3:54 ` [PATCH v7 11/14] net/sxe: add custom cmd led ctrl Jie Liu
2025-07-14 3:54 ` [PATCH v7 12/14] net/sxe: add simd function Jie Liu
2025-07-14 3:54 ` [PATCH v7 13/14] net/sxe: add virtual function Jie Liu
2025-07-14 3:54 ` [PATCH v7 14/14] net/sxe: add Solve compilation problems Jie Liu
2025-07-15 3:41 ` [PATCH v8 01/14] net/sxe: add base driver directory and doc Jie Liu
2025-07-15 3:41 ` [PATCH v8 02/14] net/sxe: add ethdev probe and remove Jie Liu
2025-07-15 3:41 ` [PATCH v8 03/14] net/sxe: add tx rx setup and data path Jie Liu
2025-07-15 3:41 ` [PATCH v8 04/14] net/sxe: add link, flow ctrl, mac ops, mtu ops function Jie Liu
2025-07-15 3:41 ` [PATCH v8 05/14] net/sxe: support vlan filter Jie Liu
2025-07-15 3:41 ` [PATCH v8 06/14] net/sxe: add filter function Jie Liu
2025-07-15 3:41 ` [PATCH v8 07/14] net/sxe: support rss offload Jie Liu
2025-07-15 3:41 ` [PATCH v8 08/14] net/sxe: add dcb function Jie Liu
2025-07-15 3:41 ` [PATCH v8 09/14] net/sxe: support ptp Jie Liu
2025-07-15 3:41 ` [PATCH v8 10/14] net/sxe: add xstats function Jie Liu
2025-07-15 3:41 ` [PATCH v8 11/14] net/sxe: add custom cmd led ctrl Jie Liu
2025-07-15 3:41 ` [PATCH v8 12/14] net/sxe: add simd function Jie Liu
2025-07-15 3:41 ` [PATCH v8 13/14] net/sxe: add virtual function Jie Liu
2025-07-15 3:41 ` [PATCH v8 14/14] net/sxe: add Solve compilation problems Jie Liu
2025-07-16 8:29 ` [PATCH v9 01/14] net/sxe: add base driver directory and doc Jie Liu
2025-07-16 8:29 ` [PATCH v9 02/14] net/sxe: add ethdev probe and remove Jie Liu
2025-07-16 20:35 ` Stephen Hemminger
2025-07-16 20:35 ` Stephen Hemminger
2025-07-16 20:36 ` Stephen Hemminger
2025-07-16 20:40 ` Stephen Hemminger
2025-07-17 16:50 ` Stephen Hemminger
2025-07-16 8:29 ` [PATCH v9 03/14] net/sxe: add tx rx setup and data path Jie Liu
2025-07-16 17:42 ` Stephen Hemminger
2025-07-16 17:49 ` Stephen Hemminger
2025-07-16 17:51 ` Stephen Hemminger
2025-07-16 8:29 ` [PATCH v9 04/14] net/sxe: add link, flow ctrl, mac ops, mtu ops function Jie Liu
2025-07-16 8:29 ` [PATCH v9 05/14] net/sxe: support vlan filter Jie Liu
2025-07-16 8:29 ` [PATCH v9 06/14] net/sxe: add filter function Jie Liu
2025-07-17 16:52 ` Stephen Hemminger
2025-07-16 8:29 ` [PATCH v9 07/14] net/sxe: support rss offload Jie Liu
2025-07-16 8:29 ` [PATCH v9 08/14] net/sxe: add dcb function Jie Liu
2025-07-17 16:39 ` Stephen Hemminger
2025-07-16 8:29 ` [PATCH v9 09/14] net/sxe: support ptp Jie Liu
2025-07-16 8:29 ` [PATCH v9 10/14] net/sxe: add xstats function Jie Liu
2025-07-16 8:29 ` [PATCH v9 11/14] net/sxe: add custom cmd led ctrl Jie Liu
2025-07-16 8:29 ` [PATCH v9 12/14] net/sxe: add simd function Jie Liu
2025-07-16 8:29 ` [PATCH v9 13/14] net/sxe: add virtual function Jie Liu
2025-07-16 17:44 ` Stephen Hemminger
2025-07-17 16:45 ` Stephen Hemminger
2025-07-16 8:29 ` [PATCH v9 14/14] net/sxe: add Solve compilation problems Jie Liu
2025-07-16 20:31 ` Stephen Hemminger
2025-07-19 9:05 ` [PATCH v10 01/14] net/sxe: add base driver directory and doc Jie Liu
2025-07-19 9:05 ` [PATCH v10 02/14] net/sxe: add ethdev probe and remove Jie Liu
2025-07-21 15:27 ` Stephen Hemminger
2025-07-19 9:05 ` [PATCH v10 03/14] net/sxe: add tx rx setup and data path Jie Liu
2025-07-21 15:28 ` Stephen Hemminger
2025-07-19 9:05 ` [PATCH v10 04/14] net/sxe: add link, flow ctrl, mac ops, mtu ops function Jie Liu
2025-07-19 9:05 ` [PATCH v10 05/14] net/sxe: support vlan filter Jie Liu
2025-07-19 9:05 ` [PATCH v10 06/14] net/sxe: add filter function Jie Liu
2025-07-19 9:05 ` [PATCH v10 07/14] net/sxe: support rss offload Jie Liu
2025-07-19 9:05 ` [PATCH v10 08/14] net/sxe: add dcb function Jie Liu
2025-07-19 9:05 ` [PATCH v10 09/14] net/sxe: support ptp Jie Liu
2025-07-19 9:05 ` [PATCH v10 10/14] net/sxe: add xstats function Jie Liu
2025-07-21 15:32 ` Stephen Hemminger
2025-07-19 9:05 ` [PATCH v10 11/14] net/sxe: add custom cmd led ctrl Jie Liu
2025-07-19 9:05 ` [PATCH v10 12/14] net/sxe: add simd function Jie Liu
2025-07-19 9:05 ` Jie Liu [this message]
2025-07-21 15:34 ` [PATCH v10 13/14] net/sxe: add virtual function Stephen Hemminger
2025-07-19 9:05 ` [PATCH v10 14/14] net/sxe: add Solve compilation problems Jie Liu
2025-07-21 15:25 ` Stephen Hemminger
2025-07-21 15:37 ` Stephen Hemminger
2025-07-25 10:48 ` [PATCH v11 01/13] net/sxe: add base driver directory and doc Jie Liu
2025-07-25 10:48 ` [PATCH v11 02/13] net/sxe: add ethdev probe and remove Jie Liu
2025-07-25 10:48 ` [PATCH v11 03/13] net/sxe: add tx rx setup and data path Jie Liu
2025-07-25 10:48 ` [PATCH v11 04/13] net/sxe: add link, flow ctrl, mac ops, mtu ops function Jie Liu
2025-07-25 10:48 ` [PATCH v11 05/13] net/sxe: support vlan filter Jie Liu
2025-07-25 10:48 ` [PATCH v11 06/13] net/sxe: add filter function Jie Liu
2025-07-25 10:48 ` [PATCH v11 07/13] net/sxe: support rss offload Jie Liu
2025-07-25 15:26 ` Ivan Malov
2025-07-25 10:48 ` [PATCH v11 08/13] net/sxe: add dcb function Jie Liu
2025-07-25 10:48 ` [PATCH v11 09/13] net/sxe: support ptp Jie Liu
2025-07-25 10:48 ` [PATCH v11 10/13] net/sxe: add xstats function Jie Liu
2025-07-25 10:48 ` [PATCH v11 11/13] net/sxe: add custom cmd led ctrl Jie Liu
2025-07-25 10:48 ` [PATCH v11 12/13] net/sxe: add simd function Jie Liu
2025-07-25 10:48 ` [PATCH v11 13/13] net/sxe: add virtual function Jie Liu
2025-07-28 9:05 ` [PATCH v12 01/13] net/sxe: add base driver directory and doc liujie5
2025-07-28 9:05 ` [PATCH v12 02/13] net/sxe: add ethdev probe and remove liujie5
2025-10-24 17:21 ` Stephen Hemminger
2025-10-24 22:14 ` Stephen Hemminger
2025-10-25 16:36 ` Stephen Hemminger
2025-07-28 9:05 ` [PATCH v12 03/13] net/sxe: add tx rx setup and data path liujie5
2025-10-24 16:46 ` Stephen Hemminger
2025-07-28 9:05 ` [PATCH v12 04/13] net/sxe: add link, flow ctrl, mac ops, mtu ops function liujie5
2025-07-28 9:05 ` [PATCH v12 05/13] net/sxe: support vlan filter liujie5
2025-07-28 9:05 ` [PATCH v12 06/13] net/sxe: add filter function liujie5
2025-07-28 9:05 ` [PATCH v12 07/13] net/sxe: support rss offload liujie5
2025-07-28 9:05 ` [PATCH v12 08/13] net/sxe: add dcb function liujie5
2025-10-24 16:38 ` Stephen Hemminger
2025-10-25 18:14 ` Stephen Hemminger
2025-07-28 9:05 ` [PATCH v12 09/13] net/sxe: support ptp liujie5
2025-07-28 9:05 ` [PATCH v12 10/13] net/sxe: add xstats function liujie5
2025-10-24 17:05 ` Stephen Hemminger
2025-10-24 17:11 ` Stephen Hemminger
2025-07-28 9:05 ` [PATCH v12 11/13] net/sxe: add custom cmd led ctrl liujie5
2025-07-28 9:05 ` [PATCH v12 12/13] net/sxe: add simd function liujie5
2025-07-28 9:05 ` [PATCH v12 13/13] net/sxe: add virtual function liujie5
2025-10-24 16:59 ` Stephen Hemminger
2025-10-24 16:59 ` Stephen Hemminger
2025-10-24 17:01 ` Stephen Hemminger
2025-10-24 17:03 ` Stephen Hemminger
2025-10-24 17:03 ` Stephen Hemminger
2025-12-25 8:11 ` [PATCH v13 01/13] net/sxe: add base driver directory and doc liujie5
2025-12-25 8:11 ` [PATCH v13 02/13] net/sxe: add ethdev probe and remove MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit liujie5
2025-12-25 8:11 ` [PATCH v13 03/13] net/sxe: add tx rx setup and data path liujie5
2025-12-25 8:11 ` [PATCH v13 04/13] net/sxe: add link, flow ctrl, mac ops, mtu ops function liujie5
2025-12-25 8:11 ` [PATCH v13 05/13] net/sxe: support vlan filter liujie5
2025-12-25 8:11 ` [PATCH v13 06/13] net/sxe: add filter function liujie5
2025-12-25 8:11 ` [PATCH v13 07/13] net/sxe: support rss offload liujie5
2025-12-25 8:11 ` [PATCH v13 08/13] net/sxe: add dcb function liujie5
2025-12-25 8:11 ` [PATCH v13 09/13] net/sxe: support ptp liujie5
2025-12-25 8:11 ` [PATCH v13 10/13] net/sxe: add xstats function liujie5
2025-12-25 8:11 ` [PATCH v13 11/13] net/sxe: add custom cmd led ctrl liujie5
2025-12-25 8:12 ` [PATCH v13 12/13] net/sxe: add simd function liujie5
2025-12-25 8:12 ` [PATCH v13 13/13] net/sxe: add virtual function liujie5
2025-12-25 9:22 ` [PATCH v14 01/13] net/sxe: add base driver directory and doc liujie5
2025-12-25 9:22 ` [PATCH v14 02/13] net/sxe: add ethdev probe and remove MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit liujie5
2025-12-25 9:22 ` [PATCH v14 03/13] net/sxe: add tx rx setup and data path liujie5
2025-12-25 9:22 ` [PATCH v14 04/13] net/sxe: add link, flow ctrl, mac ops, mtu ops function liujie5
2025-12-25 9:22 ` [PATCH v14 05/13] net/sxe: support vlan filter liujie5
2025-12-25 9:22 ` [PATCH v14 06/13] net/sxe: add filter function liujie5
2025-12-25 9:22 ` [PATCH v14 07/13] net/sxe: support rss offload liujie5
2025-12-25 9:22 ` [PATCH v14 08/13] net/sxe: add dcb function liujie5
2025-12-25 9:22 ` [PATCH v14 09/13] net/sxe: support ptp liujie5
2025-12-25 9:22 ` [PATCH v14 10/13] net/sxe: add xstats function liujie5
2025-12-25 9:22 ` [PATCH v14 11/13] net/sxe: add custom cmd led ctrl liujie5
2025-12-25 9:22 ` [PATCH v14 12/13] net/sxe: add simd function liujie5
2025-12-25 9:22 ` [PATCH v14 13/13] net/sxe: add virtual function liujie5
2026-02-08 9:31 ` [PATCH v15 01/13] net/sxe: add base driver directory and doc liujie5
2026-02-08 9:31 ` [PATCH v15 02/13] net/sxe: add ethdev probe and remove liujie5
2026-02-08 9:31 ` [PATCH v15 03/13] net/sxe: add tx rx setup and data path liujie5
2026-02-08 9:31 ` [PATCH v15 04/13] net/sxe: add link, flow ctrl, mac ops, mtu ops function liujie5
2026-02-08 9:31 ` [PATCH v15 05/13] net/sxe: support vlan filter liujie5
2026-02-08 9:31 ` [PATCH v15 06/13] net/sxe: add filter function liujie5
2026-02-08 9:31 ` [PATCH v15 07/13] net/sxe: support rss offload liujie5
2026-02-08 9:31 ` [PATCH v15 08/13] net/sxe: add dcb function liujie5
2026-02-08 9:31 ` [PATCH v15 09/13] net/sxe: support ptp liujie5
2026-02-08 9:31 ` [PATCH v15 10/13] net/sxe: add xstats function liujie5
2026-02-08 9:31 ` [PATCH v15 11/13] net/sxe: add custom cmd led ctrl liujie5
2026-02-08 9:31 ` [PATCH v15 12/13] net/sxe: add simd function liujie5
2026-02-08 9:31 ` [PATCH v15 13/13] net/sxe: add virtual function liujie5
2026-02-08 11:55 ` [PATCH v15 01/13] net/sxe: add base driver directory and doc liujie5
2026-02-08 11:55 ` [PATCH v15 02/13] net/sxe: add ethdev probe and remove liujie5
2026-02-08 11:55 ` [PATCH v15 03/13] net/sxe: add tx rx setup and data path liujie5
2026-02-08 11:55 ` [PATCH v15 04/13] net/sxe: add link, flow ctrl, mac ops, mtu ops function liujie5
2026-02-08 11:55 ` [PATCH v15 05/13] net/sxe: support vlan filter liujie5
2026-02-08 11:55 ` [PATCH v15 06/13] net/sxe: add filter function liujie5
2026-02-08 11:55 ` [PATCH v15 07/13] net/sxe: support rss offload liujie5
2026-02-08 11:55 ` [PATCH v15 08/13] net/sxe: add dcb function liujie5
2026-02-08 11:55 ` [PATCH v15 09/13] net/sxe: support ptp liujie5
2026-02-08 11:55 ` [PATCH v15 10/13] net/sxe: add xstats function liujie5
2026-02-08 11:55 ` [PATCH v15 11/13] net/sxe: add custom cmd led ctrl liujie5
2026-02-08 11:55 ` [PATCH v15 12/13] net/sxe: add simd function liujie5
2026-02-08 11:55 ` [PATCH v15 13/13] net/sxe: add virtual function liujie5
2026-02-08 11:56 ` [PATCH v16 01/13] net/sxe: add base driver directory and doc liujie5
2026-02-08 11:56 ` [PATCH v16 02/13] net/sxe: add ethdev probe and remove liujie5
2026-02-08 11:56 ` [PATCH v16 03/13] net/sxe: add tx rx setup and data path liujie5
2026-02-08 11:56 ` [PATCH v16 04/13] net/sxe: add link, flow ctrl, mac ops, mtu ops function liujie5
2026-02-08 11:56 ` [PATCH v16 05/13] net/sxe: support vlan filter liujie5
2026-02-08 11:56 ` [PATCH v16 06/13] net/sxe: add filter function liujie5
2026-02-08 11:56 ` [PATCH v16 07/13] net/sxe: support rss offload liujie5
2026-02-08 11:56 ` [PATCH v16 08/13] net/sxe: add dcb function liujie5
2026-02-08 11:56 ` [PATCH v16 09/13] net/sxe: support ptp liujie5
2026-02-08 11:56 ` [PATCH v16 10/13] net/sxe: add xstats function liujie5
2026-02-08 11:56 ` [PATCH v16 11/13] net/sxe: add custom cmd led ctrl liujie5
2026-02-08 11:56 ` [PATCH v16 12/13] net/sxe: add simd function liujie5
2026-02-08 11:56 ` [PATCH v16 13/13] net/sxe: add virtual function liujie5
2026-02-09 1:24 ` [PATCH v17 01/13] net/sxe: add base driver directory and doc liujie5
2026-02-09 1:24 ` [PATCH v17 02/13] net/sxe: add ethdev probe and remove liujie5
2026-02-09 19:05 ` Stephen Hemminger
2026-02-09 1:24 ` [PATCH v17 03/13] net/sxe: add tx rx setup and data path liujie5
2026-02-09 1:24 ` [PATCH v17 04/13] net/sxe: add link, flow ctrl, mac ops, mtu ops function liujie5
2026-02-09 1:24 ` [PATCH v17 05/13] net/sxe: support vlan filter liujie5
2026-02-09 1:24 ` [PATCH v17 06/13] net/sxe: add filter function liujie5
2026-02-09 1:24 ` [PATCH v17 07/13] net/sxe: support rss offload liujie5
2026-02-09 1:24 ` [PATCH v17 08/13] net/sxe: add dcb function liujie5
2026-02-09 1:24 ` [PATCH v17 09/13] net/sxe: support ptp liujie5
2026-02-09 1:24 ` [PATCH v17 10/13] net/sxe: add xstats function liujie5
2026-02-09 1:24 ` [PATCH v17 11/13] net/sxe: add custom cmd led ctrl liujie5
2026-02-09 1:24 ` [PATCH v17 12/13] net/sxe: add simd function liujie5
2026-02-09 1:24 ` [PATCH v17 13/13] net/sxe: add virtual function liujie5
2026-03-03 9:10 ` [PATCH v18 00/13] net/sxe: added Linkdata sxe ethernet driver liujie5
2026-03-03 9:10 ` [PATCH v18 01/13] net/sxe: add base driver directory and doc liujie5
2026-03-03 9:10 ` [PATCH v18 02/13] net/sxe: add ethdev probe and remove liujie5
2026-03-03 9:10 ` [PATCH v18 03/13] net/sxe: add tx rx setup and data path liujie5
2026-03-03 9:10 ` [PATCH v18 04/13] net/sxe: add link and mac layer operations liujie5
2026-03-03 9:10 ` [PATCH v18 05/13] net/sxe: support vlan filter liujie5
2026-03-03 9:10 ` [PATCH v18 06/13] net/sxe: add filter function liujie5
2026-03-03 9:10 ` [PATCH v18 07/13] net/sxe: support rss offload liujie5
2026-03-03 9:10 ` [PATCH v18 08/13] net/sxe: add dcb function liujie5
2026-03-03 9:10 ` [PATCH v18 09/13] net/sxe: support ptp liujie5
2026-03-03 9:10 ` [PATCH v18 10/13] net/sxe: add xstats function liujie5
2026-03-03 9:10 ` [PATCH v18 11/13] net/sxe: add custom cmd led ctrl liujie5
2026-03-03 9:10 ` [PATCH v18 12/13] net/sxe: add simd function liujie5
2026-03-03 9:10 ` [PATCH v18 13/13] net/sxe: add virtual function liujie5
2026-03-14 8:51 ` [PATCH v19 00/13] net/sxe: added Linkdata sxe ethernet driver liujie5
2026-03-14 8:51 ` [PATCH v19 01/13] net/sxe: add base driver directory and doc liujie5
2026-03-14 8:51 ` [PATCH v19 02/13] net/sxe: add ethdev probe and remove liujie5
2026-03-21 17:18 ` Stephen Hemminger
2026-03-14 8:51 ` [PATCH v19 03/13] net/sxe: add tx rx setup and data path liujie5
2026-03-14 8:51 ` [PATCH v19 04/13] net/sxe: add link and mac layer operations liujie5
2026-03-14 8:51 ` [PATCH v19 05/13] net/sxe: support vlan filter liujie5
2026-03-14 8:51 ` [PATCH v19 06/13] net/sxe: add filter function liujie5
2026-03-14 8:51 ` [PATCH v19 07/13] net/sxe: support rss offload liujie5
2026-03-14 8:52 ` [PATCH v19 08/13] net/sxe: add dcb function liujie5
2026-03-14 8:52 ` [PATCH v19 09/13] net/sxe: support ptp liujie5
2026-03-14 8:52 ` [PATCH v19 10/13] net/sxe: add xstats function liujie5
2026-03-14 8:52 ` [PATCH v19 11/13] net/sxe: add custom cmd led ctrl liujie5
2026-03-14 8:52 ` [PATCH v19 12/13] net/sxe: add simd function liujie5
2026-03-14 8:52 ` [PATCH v19 13/13] net/sxe: add virtual function liujie5
2026-03-18 3:04 ` [PATCH v19 00/13] net/sxe: added Linkdata sxe ethernet driver Stephen Hemminger
2026-03-21 17:22 ` Stephen Hemminger
2026-03-22 16:37 ` Stephen Hemminger
2026-03-03 15:42 ` [PATCH v18 " Stephen Hemminger
2026-02-09 19:01 ` [PATCH v17 01/13] net/sxe: add base driver directory and doc Stephen Hemminger
2026-02-09 19:07 ` Stephen Hemminger
2025-12-26 22:39 ` [PATCH v14 " Stephen Hemminger
2025-12-25 8:32 ` [PATCH v13 " liujie5
2025-12-25 8:32 ` [PATCH v13 02/13] net/sxe: add ethdev probe and remove MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit liujie5
2025-10-24 16:42 ` [PATCH v12 01/13] net/sxe: add base driver directory and doc Stephen Hemminger
2025-10-24 16:49 ` Stephen Hemminger
2025-10-25 18:33 ` Stephen Hemminger
2025-10-25 18:35 ` Stephen Hemminger
2025-07-16 8:42 ` [PATCH v9 01/14] " David Marchand
2025-07-16 17:46 ` Stephen Hemminger
2025-07-16 17:47 ` Stephen Hemminger
2025-07-07 14:58 ` [PATCH v3 " Stephen Hemminger
2025-07-07 15:00 ` Stephen Hemminger
2025-07-25 13:39 ` [PATCH 01/13] " Ivan Malov
2025-07-25 13:43 ` Ivan Malov
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=20250719090537.699357-13-liujie5@linkdatatechnology.com \
--to=liujie5@linkdatatechnology.com \
--cc=dev@dpdk.org \
--cc=stephen@networkplumber.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.