From: Yanling Song <songyl@ramaxel.com>
To: <dev@dpdk.org>
Cc: <songyl@ramaxel.com>, <yanling.song@linux.dev>,
<yanggan@ramaxel.com>, <xuyun@ramaxel.com>,
<ferruh.yigit@intel.com>
Subject: [PATCH v3 11/25] net/spnic: add queue pairs context initialization
Date: Fri, 24 Dec 2021 16:32:29 +0800 [thread overview]
Message-ID: <efd5ae3b5108412d34a56a1de12e0e1e6f8f1f2a.1640332922.git.songyl@ramaxel.com> (raw)
In-Reply-To: <cover.1640332922.git.songyl@ramaxel.com>
This patch adds the initialization of Tx/Rx queues
context and negotiation of NIC features.
Signed-off-by: Yanling Song <songyl@ramaxel.com>
---
drivers/net/spnic/base/spnic_hw_comm.c | 101 ++++
drivers/net/spnic/base/spnic_hw_comm.h | 6 +
drivers/net/spnic/base/spnic_nic_cfg.c | 76 +++
drivers/net/spnic/base/spnic_nic_cfg.h | 65 ++-
drivers/net/spnic/meson.build | 3 +-
drivers/net/spnic/spnic_ethdev.c | 57 +-
drivers/net/spnic/spnic_io.c | 738 +++++++++++++++++++++++++
drivers/net/spnic/spnic_io.h | 154 ++++++
drivers/net/spnic/spnic_rx.h | 113 ++++
drivers/net/spnic/spnic_tx.h | 62 +++
10 files changed, 1370 insertions(+), 5 deletions(-)
create mode 100644 drivers/net/spnic/spnic_io.c
create mode 100644 drivers/net/spnic/spnic_io.h
create mode 100644 drivers/net/spnic/spnic_rx.h
create mode 100644 drivers/net/spnic/spnic_tx.h
diff --git a/drivers/net/spnic/base/spnic_hw_comm.c b/drivers/net/spnic/base/spnic_hw_comm.c
index 5cb607cf03..1c751f2403 100644
--- a/drivers/net/spnic/base/spnic_hw_comm.c
+++ b/drivers/net/spnic/base/spnic_hw_comm.c
@@ -217,6 +217,107 @@ int spnic_func_reset(void *hwdev, u64 reset_flag)
return 0;
}
+int spnic_convert_rx_buf_size(u32 rx_buf_sz, u32 *match_sz)
+{
+ u32 i, num_hw_types, best_match_sz;
+
+ if (unlikely(!match_sz || rx_buf_sz < SPNIC_RX_BUF_SIZE_32B))
+ return -EINVAL;
+
+ if (rx_buf_sz >= SPNIC_RX_BUF_SIZE_16K) {
+ best_match_sz = SPNIC_RX_BUF_SIZE_16K;
+ goto size_matched;
+ }
+
+ num_hw_types = sizeof(spnic_hw_rx_buf_size) /
+ sizeof(spnic_hw_rx_buf_size[0]);
+ best_match_sz = spnic_hw_rx_buf_size[0];
+ for (i = 0; i < num_hw_types; i++) {
+ if (rx_buf_sz == spnic_hw_rx_buf_size[i]) {
+ best_match_sz = spnic_hw_rx_buf_size[i];
+ break;
+ } else if (rx_buf_sz < spnic_hw_rx_buf_size[i]) {
+ break;
+ }
+ best_match_sz = spnic_hw_rx_buf_size[i];
+ }
+
+size_matched:
+ *match_sz = best_match_sz;
+
+ return 0;
+}
+
+static u16 get_hw_rx_buf_size(u32 rx_buf_sz)
+{
+ u16 num_hw_types = sizeof(spnic_hw_rx_buf_size) /
+ sizeof(spnic_hw_rx_buf_size[0]);
+ u16 i;
+
+ for (i = 0; i < num_hw_types; i++) {
+ if (spnic_hw_rx_buf_size[i] == rx_buf_sz)
+ return i;
+ }
+
+ PMD_DRV_LOG(WARNING, "Chip can't support rx buf size of %d", rx_buf_sz);
+
+ return DEFAULT_RX_BUF_SIZE; /* Default 2K */
+}
+
+int spnic_set_root_ctxt(void *hwdev, u32 rq_depth, u32 sq_depth, u16 rx_buf_sz)
+{
+ struct spnic_cmd_root_ctxt root_ctxt;
+ u16 out_size = sizeof(root_ctxt);
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ memset(&root_ctxt, 0, sizeof(root_ctxt));
+ root_ctxt.func_idx = spnic_global_func_id(hwdev);
+ root_ctxt.set_cmdq_depth = 0;
+ root_ctxt.cmdq_depth = 0;
+ root_ctxt.lro_en = 1;
+ root_ctxt.rq_depth = (u16)ilog2(rq_depth);
+ root_ctxt.rx_buf_sz = get_hw_rx_buf_size(rx_buf_sz);
+ root_ctxt.sq_depth = (u16)ilog2(sq_depth);
+
+ err = spnic_msg_to_mgmt_sync(hwdev, SPNIC_MOD_COMM, MGMT_CMD_SET_VAT,
+ &root_ctxt, sizeof(root_ctxt),
+ &root_ctxt, &out_size, 0);
+ if (err || !out_size || root_ctxt.status) {
+ PMD_DRV_LOG(ERR, "Set root context failed, err: %d, status: 0x%x, out_size: 0x%x",
+ err, root_ctxt.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int spnic_clean_root_ctxt(void *hwdev)
+{
+ struct spnic_cmd_root_ctxt root_ctxt;
+ u16 out_size = sizeof(root_ctxt);
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ memset(&root_ctxt, 0, sizeof(root_ctxt));
+ root_ctxt.func_idx = spnic_global_func_id(hwdev);
+
+ err = spnic_msg_to_mgmt_sync(hwdev, SPNIC_MOD_COMM, MGMT_CMD_SET_VAT,
+ &root_ctxt, sizeof(root_ctxt),
+ &root_ctxt, &out_size, 0);
+ if (err || !out_size || root_ctxt.status) {
+ PMD_DRV_LOG(ERR, "Clean root context failed, err: %d, status: 0x%x, out_size: 0x%x",
+ err, root_ctxt.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
int spnic_set_cmdq_depth(void *hwdev, u16 cmdq_depth)
{
struct spnic_cmd_root_ctxt root_ctxt;
diff --git a/drivers/net/spnic/base/spnic_hw_comm.h b/drivers/net/spnic/base/spnic_hw_comm.h
index cf4328a04b..4573595a89 100644
--- a/drivers/net/spnic/base/spnic_hw_comm.h
+++ b/drivers/net/spnic/base/spnic_hw_comm.h
@@ -180,6 +180,10 @@ int spnic_get_mgmt_version(void *hwdev, char *mgmt_ver, int max_mgmt_len);
int spnic_get_board_info(void *hwdev, struct spnic_board_info *info);
+int spnic_set_root_ctxt(void *hwdev, u32 rq_depth, u32 sq_depth, u16 rx_buf_sz);
+
+int spnic_clean_root_ctxt(void *hwdev);
+
int spnic_get_interrupt_cfg(void *dev, struct interrupt_info *info);
int spnic_set_interrupt_cfg(void *dev, struct interrupt_info info);
@@ -188,6 +192,8 @@ int spnic_set_wq_page_size(void *hwdev, u16 func_idx, u32 page_size);
int spnic_set_cmdq_depth(void *hwdev, u16 cmdq_depth);
+int spnic_convert_rx_buf_size(u32 rx_buf_sz, u32 *match_sz);
+
int spnic_get_comm_features(void *hwdev, u64 *s_feature, u16 size);
int spnic_set_comm_features(void *hwdev, u64 *s_feature, u16 size);
diff --git a/drivers/net/spnic/base/spnic_nic_cfg.c b/drivers/net/spnic/base/spnic_nic_cfg.c
index 886aaea384..25d98d67dd 100644
--- a/drivers/net/spnic/base/spnic_nic_cfg.c
+++ b/drivers/net/spnic/base/spnic_nic_cfg.c
@@ -75,6 +75,42 @@ int l2nic_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size,
in_size, buf_out, out_size, 0);
}
+int spnic_set_ci_table(void *hwdev, struct spnic_sq_attr *attr)
+{
+ struct spnic_cmd_cons_idx_attr cons_idx_attr;
+ u16 out_size = sizeof(cons_idx_attr);
+ int err;
+
+ if (!hwdev || !attr)
+ return -EINVAL;
+
+ memset(&cons_idx_attr, 0, sizeof(cons_idx_attr));
+ cons_idx_attr.func_idx = spnic_global_func_id(hwdev);
+ cons_idx_attr.dma_attr_off = attr->dma_attr_off;
+ cons_idx_attr.pending_limit = attr->pending_limit;
+ cons_idx_attr.coalescing_time = attr->coalescing_time;
+
+ if (attr->intr_en) {
+ cons_idx_attr.intr_en = attr->intr_en;
+ cons_idx_attr.intr_idx = attr->intr_idx;
+ }
+
+ cons_idx_attr.l2nic_sqn = attr->l2nic_sqn;
+ cons_idx_attr.ci_addr = attr->ci_dma_base;
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_CMD_SQ_CI_ATTR_SET,
+ &cons_idx_attr, sizeof(cons_idx_attr),
+ &cons_idx_attr, &out_size);
+ if (err || !out_size || cons_idx_attr.msg_head.status) {
+ PMD_DRV_LOG(ERR, "Set ci attribute table failed, err: %d, "
+ "status: 0x%x, out_size: 0x%x",
+ err, cons_idx_attr.msg_head.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
static int spnic_check_mac_info(u8 status, u16 vlan_id)
{
if ((status && status != SPNIC_MGMT_STATUS_EXIST &&
@@ -406,6 +442,46 @@ int spnic_set_port_mtu(void *hwdev, u16 new_mtu)
&func_tbl_cfg);
}
+static int nic_feature_nego(void *hwdev, u8 opcode, u64 *s_feature, u16 size)
+{
+ struct spnic_cmd_feature_nego feature_nego;
+ u16 out_size = sizeof(feature_nego);
+ int err;
+
+ if (!hwdev || !s_feature || size > MAX_FEATURE_QWORD)
+ return -EINVAL;
+
+ memset(&feature_nego, 0, sizeof(feature_nego));
+ feature_nego.func_id = spnic_global_func_id(hwdev);
+ feature_nego.opcode = opcode;
+ if (opcode == SPNIC_CMD_OP_SET)
+ memcpy(feature_nego.s_feature, s_feature, size * sizeof(u64));
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_CMD_FEATURE_NEGO,
+ &feature_nego, sizeof(feature_nego),
+ &feature_nego, &out_size);
+ if (err || !out_size || feature_nego.msg_head.status) {
+ PMD_DRV_LOG(ERR, "Failed to negotiate nic feature, err:%d, status: 0x%x, out_size: 0x%x\n",
+ err, feature_nego.msg_head.status, out_size);
+ return -EFAULT;
+ }
+
+ if (opcode == SPNIC_CMD_OP_GET)
+ memcpy(s_feature, feature_nego.s_feature, size * sizeof(u64));
+
+ return 0;
+}
+
+int spnic_get_feature_from_hw(void *hwdev, u64 *s_feature, u16 size)
+{
+ return nic_feature_nego(hwdev, SPNIC_CMD_OP_GET, s_feature, size);
+}
+
+int spnic_set_feature_to_hw(void *hwdev, u64 *s_feature, u16 size)
+{
+ return nic_feature_nego(hwdev, SPNIC_CMD_OP_SET, s_feature, size);
+}
+
static int spnic_vf_func_init(void *hwdev)
{
struct spnic_cmd_register_vf register_info;
diff --git a/drivers/net/spnic/base/spnic_nic_cfg.h b/drivers/net/spnic/base/spnic_nic_cfg.h
index 0af4588c1a..a7ff44a891 100644
--- a/drivers/net/spnic/base/spnic_nic_cfg.h
+++ b/drivers/net/spnic/base/spnic_nic_cfg.h
@@ -36,6 +36,15 @@
#define SPNIC_MGMT_STATUS_EXIST 0x6
#define CHECK_IPSU_15BIT 0x8000
+struct spnic_cmd_feature_nego {
+ struct mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode; /* 1: set, 0: get */
+ u8 rsvd;
+ u64 s_feature[MAX_FEATURE_QWORD];
+};
+
/* Structures for port info */
struct nic_port_info {
u8 port_type;
@@ -69,6 +78,30 @@ enum nic_speed_level {
LINK_SPEED_LEVELS,
};
+struct spnic_sq_attr {
+ u8 dma_attr_off;
+ u8 pending_limit;
+ u8 coalescing_time;
+ u8 intr_en;
+ u16 intr_idx;
+ u32 l2nic_sqn;
+ u64 ci_dma_base;
+};
+
+struct spnic_cmd_cons_idx_attr {
+ struct mgmt_msg_head msg_head;
+
+ u16 func_idx;
+ u8 dma_attr_off;
+ u8 pending_limit;
+ u8 coalescing_time;
+ u8 intr_en;
+ u16 intr_idx;
+ u32 l2nic_sqn;
+ u32 rsvd;
+ u64 ci_addr;
+};
+
struct spnic_port_mac_set {
struct mgmt_msg_head msg_head;
@@ -88,7 +121,6 @@ struct spnic_port_mac_update {
u16 rsvd2;
u8 new_mac[ETH_ALEN];
};
-
struct spnic_cmd_port_info {
struct mgmt_msg_head msg_head;
@@ -193,6 +225,9 @@ struct spnic_cmd_set_func_tbl {
struct spnic_func_tbl_cfg tbl_cfg;
};
+#define SPNIC_CMD_OP_GET 0
+#define SPNIC_CMD_OP_SET 1
+
enum {
SPNIC_IFLA_VF_LINK_STATE_AUTO, /* Link state of the uplink */
SPNIC_IFLA_VF_LINK_STATE_ENABLE, /* Link always up */
@@ -223,6 +258,8 @@ struct spnic_cmd_register_vf {
int l2nic_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size,
void *buf_out, u16 *out_size);
+int spnic_set_ci_table(void *hwdev, struct spnic_sq_attr *attr);
+
/**
* Update MAC address to hardware
*
@@ -390,4 +427,30 @@ int spnic_init_function_table(void *hwdev, u16 rx_buff_len);
* @retval non-zero : Failure
*/
int spnic_vf_get_default_cos(void *hwdev, u8 *cos_id);
+
+/**
+ * Get service feature HW supported
+ *
+ * @param[in] dev
+ * Device pointer to hwdev
+ * @param[in] size
+ * s_feature's array size
+ * @param[out] s_feature
+ * s_feature HW supported
+ * @retval zero: Success
+ * @retval non-zero: Failure
+ */
+int spnic_get_feature_from_hw(void *hwdev, u64 *s_feature, u16 size);
+
+/**
+ * Set service feature driver supported to hardware
+ *
+ * @param[in] dev
+ * Device pointer to hwdev
+ *
+ * @retval zero: Success
+ * @retval non-zero: Failure
+ */
+int spnic_set_feature_to_hw(void *hwdev, u64 *s_feature, u16 size);
+
#endif /* _SPNIC_NIC_CFG_H_ */
diff --git a/drivers/net/spnic/meson.build b/drivers/net/spnic/meson.build
index c585aaf7f6..16056679f8 100644
--- a/drivers/net/spnic/meson.build
+++ b/drivers/net/spnic/meson.build
@@ -12,6 +12,7 @@ objs = [base_objs]
sources = files(
'spnic_ethdev.c',
- )
+ 'spnic_io.c',
+)
includes += include_directories('base')
diff --git a/drivers/net/spnic/spnic_ethdev.c b/drivers/net/spnic/spnic_ethdev.c
index 7f73e70df1..4205ab43a4 100644
--- a/drivers/net/spnic/spnic_ethdev.c
+++ b/drivers/net/spnic/spnic_ethdev.c
@@ -22,14 +22,25 @@
#include "base/spnic_hw_comm.h"
#include "base/spnic_nic_cfg.h"
#include "base/spnic_nic_event.h"
+#include "spnic_io.h"
+#include "spnic_tx.h"
+#include "spnic_rx.h"
#include "spnic_ethdev.h"
/* Driver-specific log messages type */
int spnic_logtype;
+#define SPNIC_DEFAULT_RX_FREE_THRESH 32
+#define SPNIC_DEFAULT_TX_FREE_THRESH 32
+
#define SPNIC_MAX_UC_MAC_ADDRS 128
#define SPNIC_MAX_MC_MAC_ADDRS 128
+#define SPNIC_MAX_QUEUE_DEPTH 16384
+#define SPNIC_MIN_QUEUE_DEPTH 128
+#define SPNIC_TXD_ALIGN 1
+#define SPNIC_RXD_ALIGN 1
+
/**
* Deinit mac_vlan table in hardware.
*
@@ -219,6 +230,7 @@ static void spnic_deinit_sw_rxtxqs(struct spnic_nic_dev *nic_dev)
static int spnic_dev_start(struct rte_eth_dev *eth_dev)
{
struct spnic_nic_dev *nic_dev;
+ u64 nic_features;
int err;
nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
@@ -230,6 +242,26 @@ static int spnic_dev_start(struct rte_eth_dev *eth_dev)
goto init_func_tbl_fail;
}
+ nic_features = spnic_get_driver_feature(nic_dev->hwdev);
+ nic_features &= DEFAULT_DRV_FEATURE;
+ spnic_update_driver_feature(nic_dev->hwdev, nic_features);
+
+ err = spnic_set_feature_to_hw(nic_dev->hwdev, &nic_dev->feature_cap, 1);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Failed to set nic features to hardware, err %d\n",
+ err);
+ goto get_feature_err;
+ }
+
+
+ /* Init txq and rxq context */
+ err = spnic_init_qp_ctxts(nic_dev);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Init qp context failed, dev_name: %s",
+ eth_dev->data->name);
+ goto init_qp_fail;
+ }
+
/* Set default mtu */
err = spnic_set_port_mtu(nic_dev->hwdev, nic_dev->mtu_size);
if (err) {
@@ -238,7 +270,6 @@ static int spnic_dev_start(struct rte_eth_dev *eth_dev)
goto set_mtu_fail;
}
-
/* Update eth_dev link status */
if (eth_dev->data->dev_conf.intr_conf.lsc != 0)
(void)spnic_link_update(eth_dev, 0);
@@ -248,6 +279,10 @@ static int spnic_dev_start(struct rte_eth_dev *eth_dev)
return 0;
set_mtu_fail:
+ spnic_free_qp_ctxts(nic_dev->hwdev);
+
+init_qp_fail:
+get_feature_err:
init_func_tbl_fail:
return err;
@@ -278,6 +313,9 @@ static int spnic_dev_stop(struct rte_eth_dev *dev)
memset(&link, 0, sizeof(link));
(void)rte_eth_linkstatus_set(dev, &link);
+ /* Clean root context */
+ spnic_free_qp_ctxts(nic_dev->hwdev);
+
return 0;
}
@@ -290,7 +328,7 @@ static int spnic_dev_stop(struct rte_eth_dev *dev)
static int spnic_dev_close(struct rte_eth_dev *eth_dev)
{
struct spnic_nic_dev *nic_dev =
- SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
+ SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
if (rte_bit_relaxed_test_and_set32(SPNIC_DEV_CLOSE, &nic_dev->dev_status)) {
PMD_DRV_LOG(WARNING, "Device %s already closed",
@@ -306,7 +344,6 @@ static int spnic_dev_close(struct rte_eth_dev *eth_dev)
rte_bit_relaxed_clear32(SPNIC_DEV_INTR_EN, &nic_dev->dev_status);
-
/* Destroy rx mode mutex */
spnic_mutex_destroy(&nic_dev->rx_mode_mutex);
@@ -736,6 +773,12 @@ static int spnic_func_init(struct rte_eth_dev *eth_dev)
goto init_hwdev_fail;
}
+ if (!spnic_support_nic(nic_dev->hwdev)) {
+ PMD_DRV_LOG(ERR, "Hw of %s don't support nic\n",
+ eth_dev->data->name);
+ goto init_hwdev_fail;
+ }
+
nic_dev->max_sqs = spnic_func_max_sqs(nic_dev->hwdev);
nic_dev->max_rqs = spnic_func_max_rqs(nic_dev->hwdev);
@@ -751,6 +794,13 @@ static int spnic_func_init(struct rte_eth_dev *eth_dev)
goto init_nic_hwdev_fail;
}
+ err = spnic_get_feature_from_hw(nic_dev->hwdev, &nic_dev->feature_cap, 1);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Get nic feature from hardware failed, dev_name: %s",
+ eth_dev->data->name);
+ goto get_cap_fail;
+ }
+
err = spnic_init_sw_rxtxqs(nic_dev);
if (err) {
PMD_DRV_LOG(ERR, "Init sw rxqs or txqs failed, dev_name: %s",
@@ -792,6 +842,7 @@ static int spnic_func_init(struct rte_eth_dev *eth_dev)
init_sw_rxtxqs_fail:
spnic_free_nic_hwdev(nic_dev->hwdev);
+get_cap_fail:
init_nic_hwdev_fail:
spnic_free_hwdev(nic_dev->hwdev);
eth_dev->dev_ops = NULL;
diff --git a/drivers/net/spnic/spnic_io.c b/drivers/net/spnic/spnic_io.c
new file mode 100644
index 0000000000..3603d83e5f
--- /dev/null
+++ b/drivers/net/spnic/spnic_io.c
@@ -0,0 +1,738 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#include <rte_io.h>
+#include <rte_pci.h>
+#include <rte_bus_pci.h>
+#include <ethdev_pci.h>
+#include <rte_mbuf.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_mempool.h>
+#include <rte_errno.h>
+#include <rte_ether.h>
+#include <rte_ethdev_core.h>
+#include <ethdev_driver.h>
+
+#include "base/spnic_compat.h"
+#include "base/spnic_cmd.h"
+#include "base/spnic_wq.h"
+#include "base/spnic_mgmt.h"
+#include "base/spnic_cmdq.h"
+#include "base/spnic_hwdev.h"
+#include "base/spnic_hw_comm.h"
+#include "base/spnic_nic_cfg.h"
+#include "base/spnic_hw_cfg.h"
+#include "spnic_io.h"
+#include "spnic_tx.h"
+#include "spnic_rx.h"
+#include "spnic_ethdev.h"
+
+#define SPNIC_DEAULT_TX_CI_PENDING_LIMIT 0
+#define SPNIC_DEAULT_TX_CI_COALESCING_TIME 0
+#define SPNIC_DEAULT_DROP_THD_ON 0xFFFF
+#define SPNIC_DEAULT_DROP_THD_OFF 0
+
+#define WQ_PREFETCH_MAX 4
+#define WQ_PREFETCH_MIN 1
+#define WQ_PREFETCH_THRESHOLD 256
+
+#define SPNIC_Q_CTXT_MAX 31
+
+enum spnic_qp_ctxt_type {
+ SPNIC_QP_CTXT_TYPE_SQ,
+ SPNIC_QP_CTXT_TYPE_RQ,
+};
+
+struct spnic_qp_ctxt_header {
+ u16 num_queues;
+ u16 queue_type;
+ u16 start_qid;
+ u16 rsvd;
+};
+
+struct spnic_sq_ctxt {
+ u32 ci_pi;
+ u32 drop_mode_sp;
+ u32 wq_pfn_hi_owner;
+ u32 wq_pfn_lo;
+
+ u32 rsvd0;
+ u32 pkt_drop_thd;
+ u32 global_sq_id;
+ u32 vlan_ceq_attr;
+
+ u32 pref_cache;
+ u32 pref_ci_owner;
+ u32 pref_wq_pfn_hi_ci;
+ u32 pref_wq_pfn_lo;
+
+ u32 rsvd8;
+ u32 rsvd9;
+ u32 wq_block_pfn_hi;
+ u32 wq_block_pfn_lo;
+};
+
+struct spnic_rq_ctxt {
+ u32 ci_pi;
+ u32 ceq_attr;
+ u32 wq_pfn_hi_type_owner;
+ u32 wq_pfn_lo;
+
+ u32 rsvd[3];
+ u32 cqe_sge_len;
+
+ u32 pref_cache;
+ u32 pref_ci_owner;
+ u32 pref_wq_pfn_hi_ci;
+ u32 pref_wq_pfn_lo;
+
+ u32 pi_paddr_hi;
+ u32 pi_paddr_lo;
+ u32 wq_block_pfn_hi;
+ u32 wq_block_pfn_lo;
+};
+
+struct spnic_sq_ctxt_block {
+ struct spnic_qp_ctxt_header cmdq_hdr;
+ struct spnic_sq_ctxt sq_ctxt[SPNIC_Q_CTXT_MAX];
+};
+
+struct spnic_rq_ctxt_block {
+ struct spnic_qp_ctxt_header cmdq_hdr;
+ struct spnic_rq_ctxt rq_ctxt[SPNIC_Q_CTXT_MAX];
+};
+
+struct spnic_clean_queue_ctxt {
+ struct spnic_qp_ctxt_header cmdq_hdr;
+ u32 rsvd;
+};
+
+#define SQ_CTXT_SIZE(num_sqs) ((u16)(sizeof(struct spnic_qp_ctxt_header) \
+ + (num_sqs) * sizeof(struct spnic_sq_ctxt)))
+
+#define RQ_CTXT_SIZE(num_rqs) ((u16)(sizeof(struct spnic_qp_ctxt_header) \
+ + (num_rqs) * sizeof(struct spnic_rq_ctxt)))
+
+#define CI_IDX_HIGH_SHIFH 12
+
+#define CI_HIGN_IDX(val) ((val) >> CI_IDX_HIGH_SHIFH)
+
+#define SQ_CTXT_PI_IDX_SHIFT 0
+#define SQ_CTXT_CI_IDX_SHIFT 16
+
+#define SQ_CTXT_PI_IDX_MASK 0xFFFFU
+#define SQ_CTXT_CI_IDX_MASK 0xFFFFU
+
+#define SQ_CTXT_CI_PI_SET(val, member) (((val) & \
+ SQ_CTXT_##member##_MASK) \
+ << SQ_CTXT_##member##_SHIFT)
+
+#define SQ_CTXT_MODE_SP_FLAG_SHIFT 0
+#define SQ_CTXT_MODE_PKT_DROP_SHIFT 1
+
+#define SQ_CTXT_MODE_SP_FLAG_MASK 0x1U
+#define SQ_CTXT_MODE_PKT_DROP_MASK 0x1U
+
+#define SQ_CTXT_MODE_SET(val, member) (((val) & \
+ SQ_CTXT_MODE_##member##_MASK) \
+ << SQ_CTXT_MODE_##member##_SHIFT)
+
+#define SQ_CTXT_WQ_PAGE_HI_PFN_SHIFT 0
+#define SQ_CTXT_WQ_PAGE_OWNER_SHIFT 23
+
+#define SQ_CTXT_WQ_PAGE_HI_PFN_MASK 0xFFFFFU
+#define SQ_CTXT_WQ_PAGE_OWNER_MASK 0x1U
+
+#define SQ_CTXT_WQ_PAGE_SET(val, member) (((val) & \
+ SQ_CTXT_WQ_PAGE_##member##_MASK) \
+ << SQ_CTXT_WQ_PAGE_##member##_SHIFT)
+
+#define SQ_CTXT_PKT_DROP_THD_ON_SHIFT 0
+#define SQ_CTXT_PKT_DROP_THD_OFF_SHIFT 16
+
+#define SQ_CTXT_PKT_DROP_THD_ON_MASK 0xFFFFU
+#define SQ_CTXT_PKT_DROP_THD_OFF_MASK 0xFFFFU
+
+#define SQ_CTXT_PKT_DROP_THD_SET(val, member) (((val) & \
+ SQ_CTXT_PKT_DROP_##member##_MASK) \
+ << SQ_CTXT_PKT_DROP_##member##_SHIFT)
+
+#define SQ_CTXT_GLOBAL_SQ_ID_SHIFT 0
+
+#define SQ_CTXT_GLOBAL_SQ_ID_MASK 0x1FFFU
+
+#define SQ_CTXT_GLOBAL_QUEUE_ID_SET(val, member) (((val) & \
+ SQ_CTXT_##member##_MASK) \
+ << SQ_CTXT_##member##_SHIFT)
+
+
+#define SQ_CTXT_VLAN_TAG_SHIFT 0
+#define SQ_CTXT_VLAN_TYPE_SEL_SHIFT 16
+#define SQ_CTXT_VLAN_INSERT_MODE_SHIFT 19
+#define SQ_CTXT_VLAN_CEQ_EN_SHIFT 23
+
+#define SQ_CTXT_VLAN_TAG_MASK 0xFFFFU
+#define SQ_CTXT_VLAN_TYPE_SEL_MASK 0x7U
+#define SQ_CTXT_VLAN_INSERT_MODE_MASK 0x3U
+#define SQ_CTXT_VLAN_CEQ_EN_MASK 0x1U
+
+#define SQ_CTXT_VLAN_CEQ_SET(val, member) (((val) & \
+ SQ_CTXT_VLAN_##member##_MASK) \
+ << SQ_CTXT_VLAN_##member##_SHIFT)
+
+#define SQ_CTXT_PREF_CACHE_THRESHOLD_SHIFT 0
+#define SQ_CTXT_PREF_CACHE_MAX_SHIFT 14
+#define SQ_CTXT_PREF_CACHE_MIN_SHIFT 25
+
+#define SQ_CTXT_PREF_CACHE_THRESHOLD_MASK 0x3FFFU
+#define SQ_CTXT_PREF_CACHE_MAX_MASK 0x7FFU
+#define SQ_CTXT_PREF_CACHE_MIN_MASK 0x7FU
+
+#define SQ_CTXT_PREF_CI_HI_SHIFT 0
+#define SQ_CTXT_PREF_OWNER_SHIFT 4
+
+#define SQ_CTXT_PREF_CI_HI_MASK 0xFU
+#define SQ_CTXT_PREF_OWNER_MASK 0x1U
+
+#define SQ_CTXT_PREF_WQ_PFN_HI_SHIFT 0
+#define SQ_CTXT_PREF_CI_LOW_SHIFT 20
+
+#define SQ_CTXT_PREF_WQ_PFN_HI_MASK 0xFFFFFU
+#define SQ_CTXT_PREF_CI_LOW_MASK 0xFFFU
+
+#define SQ_CTXT_PREF_SET(val, member) (((val) & \
+ SQ_CTXT_PREF_##member##_MASK) \
+ << SQ_CTXT_PREF_##member##_SHIFT)
+
+#define SQ_CTXT_WQ_BLOCK_PFN_HI_SHIFT 0
+
+#define SQ_CTXT_WQ_BLOCK_PFN_HI_MASK 0x7FFFFFU
+
+#define SQ_CTXT_WQ_BLOCK_SET(val, member) (((val) & \
+ SQ_CTXT_WQ_BLOCK_##member##_MASK) \
+ << SQ_CTXT_WQ_BLOCK_##member##_SHIFT)
+
+#define RQ_CTXT_PI_IDX_SHIFT 0
+#define RQ_CTXT_CI_IDX_SHIFT 16
+
+#define RQ_CTXT_PI_IDX_MASK 0xFFFFU
+#define RQ_CTXT_CI_IDX_MASK 0xFFFFU
+
+#define RQ_CTXT_CI_PI_SET(val, member) (((val) & \
+ RQ_CTXT_##member##_MASK) \
+ << RQ_CTXT_##member##_SHIFT)
+
+#define RQ_CTXT_CEQ_ATTR_INTR_SHIFT 21
+#define RQ_CTXT_CEQ_ATTR_INTR_ARM_SHIFT 30
+#define RQ_CTXT_CEQ_ATTR_EN_SHIFT 31
+
+#define RQ_CTXT_CEQ_ATTR_INTR_MASK 0x3FFU
+#define RQ_CTXT_CEQ_ATTR_INTR_ARM_MASK 0x1U
+#define RQ_CTXT_CEQ_ATTR_EN_MASK 0x1U
+
+#define RQ_CTXT_CEQ_ATTR_SET(val, member) (((val) & \
+ RQ_CTXT_CEQ_ATTR_##member##_MASK) \
+ << RQ_CTXT_CEQ_ATTR_##member##_SHIFT)
+
+#define RQ_CTXT_WQ_PAGE_HI_PFN_SHIFT 0
+#define RQ_CTXT_WQ_PAGE_WQE_TYPE_SHIFT 28
+#define RQ_CTXT_WQ_PAGE_OWNER_SHIFT 31
+
+#define RQ_CTXT_WQ_PAGE_HI_PFN_MASK 0xFFFFFU
+#define RQ_CTXT_WQ_PAGE_WQE_TYPE_MASK 0x3U
+#define RQ_CTXT_WQ_PAGE_OWNER_MASK 0x1U
+
+#define RQ_CTXT_WQ_PAGE_SET(val, member) (((val) & \
+ RQ_CTXT_WQ_PAGE_##member##_MASK) << \
+ RQ_CTXT_WQ_PAGE_##member##_SHIFT)
+
+#define RQ_CTXT_CQE_LEN_SHIFT 28
+
+#define RQ_CTXT_CQE_LEN_MASK 0x3U
+
+#define RQ_CTXT_CQE_LEN_SET(val, member) (((val) & \
+ RQ_CTXT_##member##_MASK) << \
+ RQ_CTXT_##member##_SHIFT)
+
+#define RQ_CTXT_PREF_CACHE_THRESHOLD_SHIFT 0
+#define RQ_CTXT_PREF_CACHE_MAX_SHIFT 14
+#define RQ_CTXT_PREF_CACHE_MIN_SHIFT 25
+
+#define RQ_CTXT_PREF_CACHE_THRESHOLD_MASK 0x3FFFU
+#define RQ_CTXT_PREF_CACHE_MAX_MASK 0x7FFU
+#define RQ_CTXT_PREF_CACHE_MIN_MASK 0x7FU
+
+#define RQ_CTXT_PREF_CI_HI_SHIFT 0
+#define RQ_CTXT_PREF_OWNER_SHIFT 4
+
+#define RQ_CTXT_PREF_CI_HI_MASK 0xFU
+#define RQ_CTXT_PREF_OWNER_MASK 0x1U
+
+#define RQ_CTXT_PREF_WQ_PFN_HI_SHIFT 0
+#define RQ_CTXT_PREF_CI_LOW_SHIFT 20
+
+#define RQ_CTXT_PREF_WQ_PFN_HI_MASK 0xFFFFFU
+#define RQ_CTXT_PREF_CI_LOW_MASK 0xFFFU
+
+#define RQ_CTXT_PREF_SET(val, member) (((val) & \
+ RQ_CTXT_PREF_##member##_MASK) << \
+ RQ_CTXT_PREF_##member##_SHIFT)
+
+#define RQ_CTXT_WQ_BLOCK_PFN_HI_SHIFT 0
+
+#define RQ_CTXT_WQ_BLOCK_PFN_HI_MASK 0x7FFFFFU
+
+#define RQ_CTXT_WQ_BLOCK_SET(val, member) (((val) & \
+ RQ_CTXT_WQ_BLOCK_##member##_MASK) << \
+ RQ_CTXT_WQ_BLOCK_##member##_SHIFT)
+
+#define SIZE_16BYTES(size) (RTE_ALIGN((size), 16) >> 4)
+
+#define WQ_PAGE_PFN_SHIFT 12
+#define WQ_BLOCK_PFN_SHIFT 9
+
+#define WQ_PAGE_PFN(page_addr) ((page_addr) >> WQ_PAGE_PFN_SHIFT)
+#define WQ_BLOCK_PFN(page_addr) ((page_addr) >> WQ_BLOCK_PFN_SHIFT)
+
+static void
+spnic_qp_prepare_cmdq_header(struct spnic_qp_ctxt_header *qp_ctxt_hdr,
+ enum spnic_qp_ctxt_type ctxt_type,
+ u16 num_queues, u16 q_id)
+{
+ qp_ctxt_hdr->queue_type = ctxt_type;
+ qp_ctxt_hdr->num_queues = num_queues;
+ qp_ctxt_hdr->start_qid = q_id;
+ qp_ctxt_hdr->rsvd = 0;
+
+ spnic_cpu_to_be32(qp_ctxt_hdr, sizeof(*qp_ctxt_hdr));
+}
+
+static void spnic_sq_prepare_ctxt(struct spnic_txq *sq, u16 sq_id,
+ struct spnic_sq_ctxt *sq_ctxt)
+{
+ u64 wq_page_addr;
+ u64 wq_page_pfn, wq_block_pfn;
+ u32 wq_page_pfn_hi, wq_page_pfn_lo;
+ u32 wq_block_pfn_hi, wq_block_pfn_lo;
+ u16 pi_start, ci_start;
+
+ ci_start = sq->cons_idx & sq->q_mask;
+ pi_start = sq->prod_idx & sq->q_mask;
+
+ /* Read the first page from hardware table */
+ wq_page_addr = sq->queue_buf_paddr;
+
+ wq_page_pfn = WQ_PAGE_PFN(wq_page_addr);
+ wq_page_pfn_hi = upper_32_bits(wq_page_pfn);
+ wq_page_pfn_lo = lower_32_bits(wq_page_pfn);
+
+ /* Use 0-level CLA */
+ wq_block_pfn = WQ_BLOCK_PFN(wq_page_addr);
+ wq_block_pfn_hi = upper_32_bits(wq_block_pfn);
+ wq_block_pfn_lo = lower_32_bits(wq_block_pfn);
+
+ sq_ctxt->ci_pi = SQ_CTXT_CI_PI_SET(ci_start, CI_IDX) |
+ SQ_CTXT_CI_PI_SET(pi_start, PI_IDX);
+
+ sq_ctxt->drop_mode_sp = SQ_CTXT_MODE_SET(0, SP_FLAG) |
+ SQ_CTXT_MODE_SET(0, PKT_DROP);
+
+ sq_ctxt->wq_pfn_hi_owner = SQ_CTXT_WQ_PAGE_SET(wq_page_pfn_hi, HI_PFN) |
+ SQ_CTXT_WQ_PAGE_SET(1, OWNER);
+
+ sq_ctxt->wq_pfn_lo = wq_page_pfn_lo;
+
+ sq_ctxt->pkt_drop_thd =
+ SQ_CTXT_PKT_DROP_THD_SET(SPNIC_DEAULT_DROP_THD_ON, THD_ON) |
+ SQ_CTXT_PKT_DROP_THD_SET(SPNIC_DEAULT_DROP_THD_OFF, THD_OFF);
+
+ sq_ctxt->global_sq_id =
+ SQ_CTXT_GLOBAL_QUEUE_ID_SET(sq_id, GLOBAL_SQ_ID);
+
+ /* Insert c-vlan in default */
+ sq_ctxt->vlan_ceq_attr = SQ_CTXT_VLAN_CEQ_SET(0, CEQ_EN) |
+ SQ_CTXT_VLAN_CEQ_SET(1, INSERT_MODE);
+
+ sq_ctxt->rsvd0 = 0;
+
+ sq_ctxt->pref_cache = SQ_CTXT_PREF_SET(WQ_PREFETCH_MIN, CACHE_MIN) |
+ SQ_CTXT_PREF_SET(WQ_PREFETCH_MAX, CACHE_MAX) |
+ SQ_CTXT_PREF_SET(WQ_PREFETCH_THRESHOLD,
+ CACHE_THRESHOLD);
+
+ sq_ctxt->pref_ci_owner =
+ SQ_CTXT_PREF_SET(CI_HIGN_IDX(ci_start), CI_HI) |
+ SQ_CTXT_PREF_SET(1, OWNER);
+
+ sq_ctxt->pref_wq_pfn_hi_ci =
+ SQ_CTXT_PREF_SET(ci_start, CI_LOW) |
+ SQ_CTXT_PREF_SET(wq_page_pfn_hi, WQ_PFN_HI);
+
+ sq_ctxt->pref_wq_pfn_lo = wq_page_pfn_lo;
+
+ sq_ctxt->wq_block_pfn_hi =
+ SQ_CTXT_WQ_BLOCK_SET(wq_block_pfn_hi, PFN_HI);
+
+ sq_ctxt->wq_block_pfn_lo = wq_block_pfn_lo;
+
+ spnic_cpu_to_be32(sq_ctxt, sizeof(*sq_ctxt));
+}
+
+static void spnic_rq_prepare_ctxt(struct spnic_rxq *rq,
+ struct spnic_rq_ctxt *rq_ctxt)
+{
+ u64 wq_page_addr;
+ u64 wq_page_pfn, wq_block_pfn;
+ u32 wq_page_pfn_hi, wq_page_pfn_lo;
+ u32 wq_block_pfn_hi, wq_block_pfn_lo;
+ u16 pi_start, ci_start;
+ u16 wqe_type = rq->wqebb_shift - SPNIC_RQ_WQEBB_SHIFT;
+ u8 intr_disable;
+
+ /* RQ depth is in unit of 8 Bytes */
+ ci_start = (u16)((rq->cons_idx & rq->q_mask) << wqe_type);
+ pi_start = (u16)((rq->prod_idx & rq->q_mask) << wqe_type);
+
+ /* Read the first page from hardware table */
+ wq_page_addr = rq->queue_buf_paddr;
+
+ wq_page_pfn = WQ_PAGE_PFN(wq_page_addr);
+ wq_page_pfn_hi = upper_32_bits(wq_page_pfn);
+ wq_page_pfn_lo = lower_32_bits(wq_page_pfn);
+
+ /* Use 0-level CLA */
+ wq_block_pfn = WQ_BLOCK_PFN(wq_page_addr);
+
+ wq_block_pfn_hi = upper_32_bits(wq_block_pfn);
+ wq_block_pfn_lo = lower_32_bits(wq_block_pfn);
+
+ rq_ctxt->ci_pi = RQ_CTXT_CI_PI_SET(ci_start, CI_IDX) |
+ RQ_CTXT_CI_PI_SET(pi_start, PI_IDX);
+
+ intr_disable = rq->dp_intr_en ? 0 : 1;
+ rq_ctxt->ceq_attr = RQ_CTXT_CEQ_ATTR_SET(intr_disable, EN) |
+ RQ_CTXT_CEQ_ATTR_SET(0, INTR_ARM) |
+ RQ_CTXT_CEQ_ATTR_SET(rq->msix_entry_idx, INTR);
+
+ /* Use 32Byte WQE with SGE for CQE in default */
+ rq_ctxt->wq_pfn_hi_type_owner =
+ RQ_CTXT_WQ_PAGE_SET(wq_page_pfn_hi, HI_PFN) |
+ RQ_CTXT_WQ_PAGE_SET(1, OWNER);
+
+ switch (wqe_type) {
+ case SPNIC_EXTEND_RQ_WQE:
+ /* Use 32Byte WQE with SGE for CQE */
+ rq_ctxt->wq_pfn_hi_type_owner |=
+ RQ_CTXT_WQ_PAGE_SET(0, WQE_TYPE);
+ break;
+ case SPNIC_NORMAL_RQ_WQE:
+ /* Use 16Byte WQE with 32Bytes SGE for CQE */
+ rq_ctxt->wq_pfn_hi_type_owner |=
+ RQ_CTXT_WQ_PAGE_SET(2, WQE_TYPE);
+ rq_ctxt->cqe_sge_len = RQ_CTXT_CQE_LEN_SET(1, CQE_LEN);
+ break;
+ default:
+ PMD_DRV_LOG(INFO, "Invalid rq wqe type: %u", wqe_type);
+ }
+
+ rq_ctxt->wq_pfn_lo = wq_page_pfn_lo;
+
+ rq_ctxt->pref_cache =
+ RQ_CTXT_PREF_SET(WQ_PREFETCH_MIN, CACHE_MIN) |
+ RQ_CTXT_PREF_SET(WQ_PREFETCH_MAX, CACHE_MAX) |
+ RQ_CTXT_PREF_SET(WQ_PREFETCH_THRESHOLD, CACHE_THRESHOLD);
+
+ rq_ctxt->pref_ci_owner =
+ RQ_CTXT_PREF_SET(CI_HIGN_IDX(ci_start), CI_HI) |
+ RQ_CTXT_PREF_SET(1, OWNER);
+
+ rq_ctxt->pref_wq_pfn_hi_ci =
+ RQ_CTXT_PREF_SET(wq_page_pfn_hi, WQ_PFN_HI) |
+ RQ_CTXT_PREF_SET(ci_start, CI_LOW);
+
+ rq_ctxt->pref_wq_pfn_lo = wq_page_pfn_lo;
+
+ rq_ctxt->pi_paddr_hi = upper_32_bits(rq->pi_dma_addr);
+ rq_ctxt->pi_paddr_lo = lower_32_bits(rq->pi_dma_addr);
+
+ rq_ctxt->wq_block_pfn_hi =
+ RQ_CTXT_WQ_BLOCK_SET(wq_block_pfn_hi, PFN_HI);
+
+ rq_ctxt->wq_block_pfn_lo = wq_block_pfn_lo;
+
+ spnic_cpu_to_be32(rq_ctxt, sizeof(*rq_ctxt));
+}
+
+static int init_sq_ctxts(struct spnic_nic_dev *nic_dev)
+{
+ struct spnic_sq_ctxt_block *sq_ctxt_block = NULL;
+ struct spnic_sq_ctxt *sq_ctxt = NULL;
+ struct spnic_cmd_buf *cmd_buf = NULL;
+ struct spnic_txq *sq = NULL;
+ u64 out_param = 0;
+ u16 q_id, curr_id, max_ctxts, i;
+ int err = 0;
+
+ cmd_buf = spnic_alloc_cmd_buf(nic_dev->hwdev);
+ if (!cmd_buf) {
+ PMD_DRV_LOG(ERR, "Allocate cmd buf for sq ctx failed");
+ return -ENOMEM;
+ }
+
+ q_id = 0;
+ while (q_id < nic_dev->num_sqs) {
+ sq_ctxt_block = cmd_buf->buf;
+ sq_ctxt = sq_ctxt_block->sq_ctxt;
+
+ max_ctxts = (nic_dev->num_sqs - q_id) > SPNIC_Q_CTXT_MAX ?
+ SPNIC_Q_CTXT_MAX : (nic_dev->num_sqs - q_id);
+
+ spnic_qp_prepare_cmdq_header(&sq_ctxt_block->cmdq_hdr,
+ SPNIC_QP_CTXT_TYPE_SQ,
+ max_ctxts, q_id);
+
+ for (i = 0; i < max_ctxts; i++) {
+ curr_id = q_id + i;
+ sq = nic_dev->txqs[curr_id];
+ spnic_sq_prepare_ctxt(sq, curr_id, &sq_ctxt[i]);
+ }
+
+ cmd_buf->size = SQ_CTXT_SIZE(max_ctxts);
+ err = spnic_cmdq_direct_resp(nic_dev->hwdev, SPNIC_MOD_L2NIC,
+ SPNIC_UCODE_CMD_MODIFY_QUEUE_CTX,
+ cmd_buf, &out_param, 0);
+ if (err || out_param != 0) {
+ PMD_DRV_LOG(ERR, "Set SQ ctxts failed, "
+ "err: %d, out_param: %" PRIu64 "",
+ err, out_param);
+
+ err = -EFAULT;
+ break;
+ }
+
+ q_id += max_ctxts;
+ }
+
+ spnic_free_cmd_buf(cmd_buf);
+ return err;
+}
+
+static int init_rq_ctxts(struct spnic_nic_dev *nic_dev)
+{
+ struct spnic_rq_ctxt_block *rq_ctxt_block = NULL;
+ struct spnic_rq_ctxt *rq_ctxt = NULL;
+ struct spnic_cmd_buf *cmd_buf = NULL;
+ struct spnic_rxq *rq = NULL;
+ u64 out_param = 0;
+ u16 q_id, curr_id, max_ctxts, i;
+ int err = 0;
+
+ cmd_buf = spnic_alloc_cmd_buf(nic_dev->hwdev);
+ if (!cmd_buf) {
+ PMD_DRV_LOG(ERR, "Allocate cmd buf for rq ctx failed");
+ return -ENOMEM;
+ }
+
+ q_id = 0;
+ while (q_id < nic_dev->num_rqs) {
+ rq_ctxt_block = cmd_buf->buf;
+ rq_ctxt = rq_ctxt_block->rq_ctxt;
+
+ max_ctxts = (nic_dev->num_rqs - q_id) > SPNIC_Q_CTXT_MAX ?
+ SPNIC_Q_CTXT_MAX : (nic_dev->num_rqs - q_id);
+
+ spnic_qp_prepare_cmdq_header(&rq_ctxt_block->cmdq_hdr,
+ SPNIC_QP_CTXT_TYPE_RQ, max_ctxts,
+ q_id);
+
+ for (i = 0; i < max_ctxts; i++) {
+ curr_id = q_id + i;
+ rq = nic_dev->rxqs[curr_id];
+
+ spnic_rq_prepare_ctxt(rq, &rq_ctxt[i]);
+ }
+
+ cmd_buf->size = RQ_CTXT_SIZE(max_ctxts);
+ err = spnic_cmdq_direct_resp(nic_dev->hwdev, SPNIC_MOD_L2NIC,
+ SPNIC_UCODE_CMD_MODIFY_QUEUE_CTX,
+ cmd_buf, &out_param, 0);
+ if (err || out_param != 0) {
+ PMD_DRV_LOG(ERR, "Set RQ ctxts failed, "
+ "err: %d, out_param: %" PRIu64 "",
+ err, out_param);
+ err = -EFAULT;
+ break;
+ }
+
+ q_id += max_ctxts;
+ }
+
+ spnic_free_cmd_buf(cmd_buf);
+ return err;
+}
+
+static int clean_queue_offload_ctxt(struct spnic_nic_dev *nic_dev,
+ enum spnic_qp_ctxt_type ctxt_type)
+{
+ struct spnic_clean_queue_ctxt *ctxt_block = NULL;
+ struct spnic_cmd_buf *cmd_buf;
+ u64 out_param = 0;
+ int err;
+
+ cmd_buf = spnic_alloc_cmd_buf(nic_dev->hwdev);
+ if (!cmd_buf) {
+ PMD_DRV_LOG(ERR, "Allocate cmd buf for LRO/TSO space failed");
+ return -ENOMEM;
+ }
+
+ ctxt_block = cmd_buf->buf;
+ ctxt_block->cmdq_hdr.num_queues = nic_dev->max_sqs;
+ ctxt_block->cmdq_hdr.queue_type = ctxt_type;
+ ctxt_block->cmdq_hdr.start_qid = 0;
+
+ spnic_cpu_to_be32(ctxt_block, sizeof(*ctxt_block));
+
+ cmd_buf->size = sizeof(*ctxt_block);
+
+ err = spnic_cmdq_direct_resp(nic_dev->hwdev, SPNIC_MOD_L2NIC,
+ SPNIC_UCODE_CMD_CLEAN_QUEUE_CONTEXT,
+ cmd_buf, &out_param, 0);
+ if ((err) || (out_param)) {
+ PMD_DRV_LOG(ERR, "Clean queue offload ctxts failed, "
+ "err: %d, out_param: %" PRIu64 "", err, out_param);
+ err = -EFAULT;
+ }
+
+ spnic_free_cmd_buf(cmd_buf);
+ return err;
+}
+
+static int clean_qp_offload_ctxt(struct spnic_nic_dev *nic_dev)
+{
+ /* Clean LRO/TSO context space */
+ return (clean_queue_offload_ctxt(nic_dev, SPNIC_QP_CTXT_TYPE_SQ) ||
+ clean_queue_offload_ctxt(nic_dev, SPNIC_QP_CTXT_TYPE_RQ));
+}
+
+void spnic_get_func_rx_buf_size(void *dev)
+{
+ struct spnic_nic_dev *nic_dev = (struct spnic_nic_dev *)dev;
+ struct spnic_rxq *rxq = NULL;
+ u16 q_id;
+ u16 buf_size = 0;
+
+ for (q_id = 0; q_id < nic_dev->num_rqs; q_id++) {
+ rxq = nic_dev->rxqs[q_id];
+
+ if (rxq == NULL)
+ continue;
+
+ if (q_id == 0)
+ buf_size = rxq->buf_len;
+
+ buf_size = buf_size > rxq->buf_len ? rxq->buf_len : buf_size;
+ }
+
+ nic_dev->rx_buff_len = buf_size;
+}
+
+/* Init qps ctxt and set sq ci attr and arm all sq */
+int spnic_init_qp_ctxts(void *dev)
+{
+ struct spnic_nic_dev *nic_dev = NULL;
+ struct spnic_hwdev *hwdev = NULL;
+ struct spnic_sq_attr sq_attr;
+ u32 rq_depth;
+ u16 q_id;
+ int err;
+
+ if (!dev)
+ return -EINVAL;
+
+ nic_dev = (struct spnic_nic_dev *)dev;
+ hwdev = nic_dev->hwdev;
+
+ err = init_sq_ctxts(nic_dev);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Init SQ ctxts failed");
+ return err;
+ }
+
+ err = init_rq_ctxts(nic_dev);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Init RQ ctxts failed");
+ return err;
+ }
+
+ err = clean_qp_offload_ctxt(nic_dev);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Clean qp offload ctxts failed");
+ return err;
+ }
+
+ rq_depth = ((u32)nic_dev->rxqs[0]->q_depth) <<
+ nic_dev->rxqs[0]->wqe_type;
+ err = spnic_set_root_ctxt(hwdev, rq_depth, nic_dev->txqs[0]->q_depth,
+ nic_dev->rx_buff_len);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Set root context failed");
+ return err;
+ }
+
+ for (q_id = 0; q_id < nic_dev->num_sqs; q_id++) {
+ sq_attr.ci_dma_base = nic_dev->txqs[q_id]->ci_dma_base >> 2;
+ sq_attr.pending_limit = SPNIC_DEAULT_TX_CI_PENDING_LIMIT;
+ sq_attr.coalescing_time = SPNIC_DEAULT_TX_CI_COALESCING_TIME;
+ sq_attr.intr_en = 0;
+ sq_attr.intr_idx = 0; /* Tx doesn't need intr */
+ sq_attr.l2nic_sqn = q_id;
+ sq_attr.dma_attr_off = 0;
+ err = spnic_set_ci_table(hwdev, &sq_attr);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Set ci table failed");
+ goto set_cons_idx_table_err;
+ }
+ }
+
+ return 0;
+
+set_cons_idx_table_err:
+ spnic_clean_root_ctxt(hwdev);
+ return err;
+}
+
+void spnic_free_qp_ctxts(void *hwdev)
+{
+ if (!hwdev)
+ return;
+
+ spnic_clean_root_ctxt(hwdev);
+}
+
+void spnic_update_driver_feature(void *dev, u64 s_feature)
+{
+ struct spnic_nic_dev *nic_dev = NULL;
+
+ if (!dev)
+ return;
+
+ nic_dev = (struct spnic_nic_dev *)dev;
+ nic_dev->feature_cap = s_feature;
+
+ PMD_DRV_LOG(INFO, "Update nic feature to %" PRIu64 "\n",
+ nic_dev->feature_cap);
+}
+
+u64 spnic_get_driver_feature(void *dev)
+{
+ struct spnic_nic_dev *nic_dev = NULL;
+
+ if (!dev)
+ return -EINVAL;
+
+ nic_dev = (struct spnic_nic_dev *)dev;
+
+ return nic_dev->feature_cap;
+}
diff --git a/drivers/net/spnic/spnic_io.h b/drivers/net/spnic/spnic_io.h
new file mode 100644
index 0000000000..ccb8044481
--- /dev/null
+++ b/drivers/net/spnic/spnic_io.h
@@ -0,0 +1,154 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#ifndef _SPNIC_IO_H_
+#define _SPNIC_IO_H_
+
+#define SPNIC_SQ_WQEBB_SHIFT 4
+#define SPNIC_RQ_WQEBB_SHIFT 3
+
+#define SPNIC_SQ_WQEBB_SIZE BIT(SPNIC_SQ_WQEBB_SHIFT)
+#define SPNIC_CQE_SIZE_SHIFT 4
+
+/* Ci addr should RTE_CACHE_SIZE(64B) alignment for performance */
+#define SPNIC_CI_Q_ADDR_SIZE 64
+
+#define CI_TABLE_SIZE(num_qps, pg_sz) \
+ (RTE_ALIGN((num_qps) * SPNIC_CI_Q_ADDR_SIZE, pg_sz))
+
+#define SPNIC_CI_VADDR(base_addr, q_id) ((u8 *)(base_addr) + \
+ (q_id) * SPNIC_CI_Q_ADDR_SIZE)
+
+#define SPNIC_CI_PADDR(base_paddr, q_id) ((base_paddr) + \
+ (q_id) * SPNIC_CI_Q_ADDR_SIZE)
+
+enum spnic_rq_wqe_type {
+ SPNIC_COMPACT_RQ_WQE,
+ SPNIC_NORMAL_RQ_WQE,
+ SPNIC_EXTEND_RQ_WQE,
+};
+
+enum spnic_queue_type {
+ SPNIC_SQ,
+ SPNIC_RQ,
+ SPNIC_MAX_QUEUE_TYPE
+};
+
+/* Doorbell info */
+struct spnic_db {
+ u32 db_info;
+ u32 pi_hi;
+};
+
+#define DB_INFO_QID_SHIFT 0
+#define DB_INFO_NON_FILTER_SHIFT 22
+#define DB_INFO_CFLAG_SHIFT 23
+#define DB_INFO_COS_SHIFT 24
+#define DB_INFO_TYPE_SHIFT 27
+
+#define DB_INFO_QID_MASK 0x1FFFU
+#define DB_INFO_NON_FILTER_MASK 0x1U
+#define DB_INFO_CFLAG_MASK 0x1U
+#define DB_INFO_COS_MASK 0x7U
+#define DB_INFO_TYPE_MASK 0x1FU
+#define DB_INFO_SET(val, member) (((u32)(val) & \
+ DB_INFO_##member##_MASK) << \
+ DB_INFO_##member##_SHIFT)
+
+#define DB_PI_LOW_MASK 0xFFU
+#define DB_PI_HIGH_MASK 0xFFU
+#define DB_PI_LOW(pi) ((pi) & DB_PI_LOW_MASK)
+#define DB_PI_HI_SHIFT 8
+#define DB_PI_HIGH(pi) (((pi) >> DB_PI_HI_SHIFT) & DB_PI_HIGH_MASK)
+#define DB_INFO_UPPER_32(val) (((u64)val) << 32)
+
+#define DB_ADDR(db_addr, pi) ((u64 *)(db_addr) + DB_PI_LOW(pi))
+#define SRC_TYPE 1
+
+/* Cflag data path */
+#define SQ_CFLAG_DP 0
+#define RQ_CFLAG_DP 1
+
+#define MASKED_QUEUE_IDX(queue, idx) ((idx) & (queue)->q_mask)
+
+#define NIC_WQE_ADDR(queue, idx) ((void *)((u64)((queue)->queue_buf_vaddr) + \
+ ((idx) << (queue)->wqebb_shift)))
+
+#define SPNIC_FLUSH_QUEUE_TIMEOUT 3000
+
+/**
+ * Write send queue doorbell
+ *
+ * @param[in] db_addr
+ * Doorbell address
+ * @param[in] q_id
+ * Send queue id
+ * @param[in] cos
+ * Send queue cos
+ * @param[in] cflag
+ * Cflag data path
+ * @param[in] pi
+ * Send queue pi
+ */
+static inline void spnic_write_db(void *db_addr, u16 q_id, int cos, u8 cflag,
+ u16 pi)
+{
+ u64 db;
+
+ /* Hardware will do endianness converting */
+ db = DB_PI_HIGH(pi);
+ db = DB_INFO_UPPER_32(db) | DB_INFO_SET(SRC_TYPE, TYPE) |
+ DB_INFO_SET(cflag, CFLAG) | DB_INFO_SET(cos, COS) |
+ DB_INFO_SET(q_id, QID);
+
+ rte_wmb(); /* Write all before the doorbell */
+
+ rte_write64(*((u64 *)&db), DB_ADDR(db_addr, pi));
+}
+
+void spnic_get_func_rx_buf_size(void *dev);
+
+/**
+ * Init queue pair context
+ *
+ * @param[in] dev
+ * Device pointer to nic device
+ *
+ * @retval zero: Success
+ * @retval non-zero: Failure
+ */
+int spnic_init_qp_ctxts(void *dev);
+
+/**
+ * Free queue pair context
+ *
+ * @param[in] hwdev
+ * Device pointer to hwdev
+ */
+void spnic_free_qp_ctxts(void *hwdev);
+
+/**
+ * Update service feature driver supported
+ *
+ * @param[in] dev
+ * Device pointer to nic device
+ * @param[out] s_feature
+ * s_feature driver supported
+ * @retval zero: Success
+ * @retval non-zero: Failure
+ */
+void spnic_update_driver_feature(void *dev, u64 s_feature);
+
+/**
+ * Get service feature driver supported
+ *
+ * @param[in] dev
+ * Device pointer to nic device
+ * @param[out] s_feature
+ * s_feature driver supported
+ * @retval zero: Success
+ * @retval non-zero: Failure
+ */
+u64 spnic_get_driver_feature(void *dev);
+#endif /* _SPNIC_IO_H_ */
diff --git a/drivers/net/spnic/spnic_rx.h b/drivers/net/spnic/spnic_rx.h
new file mode 100644
index 0000000000..b2f0052533
--- /dev/null
+++ b/drivers/net/spnic/spnic_rx.h
@@ -0,0 +1,113 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#ifndef _SPNIC_RX_H_
+#define _SPNIC_RX_H_
+
+struct spnic_rxq_stats {
+ u64 packets;
+ u64 bytes;
+ u64 errors;
+ u64 csum_errors;
+ u64 other_errors;
+ u64 unlock_bp;
+ u64 dropped;
+
+ u64 rx_nombuf;
+ u64 rx_discards;
+ u64 burst_pkts;
+};
+
+struct spnic_rq_cqe {
+ u32 status;
+ u32 vlan_len;
+
+ u32 offload_type;
+ u32 hash_val;
+ u32 xid;
+ u32 decrypt_info;
+ u32 rsvd6;
+ u32 pkt_info;
+};
+
+/*
+ * Attention: please do not add any member in spnic_rx_info because rxq bulk
+ * rearm mode will write mbuf in rx_info
+ */
+struct spnic_rx_info {
+ struct rte_mbuf *mbuf;
+};
+
+struct spnic_sge_sect {
+ struct spnic_sge sge;
+ u32 rsvd;
+};
+
+struct spnic_rq_extend_wqe {
+ struct spnic_sge_sect buf_desc;
+ struct spnic_sge_sect cqe_sect;
+};
+
+struct spnic_rq_normal_wqe {
+ u32 buf_hi_addr;
+ u32 buf_lo_addr;
+ u32 cqe_hi_addr;
+ u32 cqe_lo_addr;
+};
+
+struct spnic_rq_wqe {
+ union {
+ struct spnic_rq_normal_wqe normal_wqe;
+ struct spnic_rq_extend_wqe extend_wqe;
+ };
+};
+
+struct spnic_rxq {
+ struct spnic_nic_dev *nic_dev;
+
+ u16 q_id;
+ u16 q_depth;
+ u16 q_mask;
+ u16 buf_len;
+
+ u32 rx_buff_shift;
+
+ u16 rx_free_thresh;
+ u16 rxinfo_align_end;
+ u16 wqebb_shift;
+ u16 wqebb_size;
+
+ u16 wqe_type;
+ u16 cons_idx;
+ u16 prod_idx;
+ u16 delta;
+
+ u16 next_to_update;
+ u16 port_id;
+
+ const struct rte_memzone *rq_mz;
+ void *queue_buf_vaddr; /* Rq dma info */
+ rte_iova_t queue_buf_paddr;
+
+ const struct rte_memzone *pi_mz;
+ u16 *pi_virt_addr;
+ void *db_addr;
+ rte_iova_t pi_dma_addr;
+
+ struct spnic_rx_info *rx_info;
+ struct spnic_rq_cqe *rx_cqe;
+ struct rte_mempool *mb_pool;
+
+ const struct rte_memzone *cqe_mz;
+ rte_iova_t cqe_start_paddr;
+ void *cqe_start_vaddr;
+ u8 dp_intr_en;
+ u16 msix_entry_idx;
+
+ unsigned long status;
+
+ struct spnic_rxq_stats rxq_stats;
+} __rte_cache_aligned;
+
+#endif /* _SPNIC_RX_H_ */
diff --git a/drivers/net/spnic/spnic_tx.h b/drivers/net/spnic/spnic_tx.h
new file mode 100644
index 0000000000..7528b27bd9
--- /dev/null
+++ b/drivers/net/spnic/spnic_tx.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#ifndef _SPNIC_TX_H_
+#define _SPNIC_TX_H_
+
+/* Txq info */
+struct spnic_txq_stats {
+ u64 packets;
+ u64 bytes;
+ u64 tx_busy;
+ u64 off_errs;
+ u64 burst_pkts;
+ u64 sge_len0;
+ u64 mbuf_null;
+ u64 cpy_pkts;
+ u64 sge_len_too_large;
+};
+
+struct spnic_tx_info {
+ struct rte_mbuf *mbuf;
+ struct rte_mbuf *cpy_mbuf;
+ int wqebb_cnt;
+};
+
+struct spnic_txq {
+ struct spnic_nic_dev *nic_dev;
+
+ u16 q_id;
+ u16 q_depth;
+ u16 q_mask;
+ u16 wqebb_size;
+
+ u16 wqebb_shift;
+ u16 cons_idx;
+ u16 prod_idx;
+
+ u16 tx_free_thresh;
+ u16 owner; /* Used for sq */
+
+ void *db_addr;
+
+ struct spnic_tx_info *tx_info;
+
+ const struct rte_memzone *sq_mz;
+ void *queue_buf_vaddr;
+ rte_iova_t queue_buf_paddr; /* Sq dma info */
+
+ const struct rte_memzone *ci_mz;
+ void *ci_vaddr_base;
+ rte_iova_t ci_dma_base;
+
+ u64 sq_head_addr;
+ u64 sq_bot_sge_addr;
+
+ u32 cos;
+
+ struct spnic_txq_stats txq_stats;
+} __rte_cache_aligned;
+
+#endif /* _SPNIC_TX_H_ */
--
2.32.0
next prev parent reply other threads:[~2021-12-24 8:34 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-24 8:32 [PATCH v3 00/25] Net/SPNIC: support SPNIC into DPDK 22.03 Yanling Song
2021-12-24 8:32 ` [PATCH v3 01/25] drivers/net: introduce a new PMD driver Yanling Song
2021-12-24 8:32 ` [PATCH v3 02/25] net/spnic: initialize the HW interface Yanling Song
2021-12-24 8:32 ` [PATCH v3 03/25] net/spnic: add mbox message channel Yanling Song
2021-12-24 8:32 ` [PATCH v3 04/25] net/spnic: introduce event queue Yanling Song
2021-12-24 8:32 ` [PATCH v3 05/25] net/spnic: add mgmt module Yanling Song
2021-12-28 15:59 ` Stephen Hemminger
2021-12-29 10:26 ` Yanling Song
2021-12-24 8:32 ` [PATCH v3 06/25] net/spnic: add cmdq and work queue Yanling Song
2021-12-24 8:32 ` [PATCH v3 07/25] net/spnic: add interface handling cmdq message Yanling Song
2021-12-24 8:32 ` [PATCH v3 08/25] net/spnic: add hardware info initialization Yanling Song
2021-12-24 8:32 ` [PATCH v3 09/25] net/spnic: support MAC and link event handling Yanling Song
2021-12-24 8:32 ` [PATCH v3 10/25] net/spnic: add function info initialization Yanling Song
2021-12-24 8:32 ` Yanling Song [this message]
2021-12-24 8:32 ` [PATCH v3 12/25] net/spnic: support mbuf handling of Tx/Rx Yanling Song
2021-12-24 8:32 ` [PATCH v3 13/25] net/spnic: support Rx congfiguration Yanling Song
2021-12-24 8:32 ` [PATCH v3 14/25] net/spnic: add port/vport enable Yanling Song
2021-12-24 8:32 ` [PATCH v3 15/25] net/spnic: support IO packets handling Yanling Song
2021-12-24 8:32 ` [PATCH v3 16/25] net/spnic: add device configure/version/info Yanling Song
2021-12-24 8:32 ` [PATCH v3 17/25] net/spnic: support RSS configuration update and get Yanling Song
2021-12-24 8:32 ` [PATCH v3 18/25] net/spnic: support VLAN filtering and offloading Yanling Song
2021-12-24 8:32 ` [PATCH v3 19/25] net/spnic: support promiscuous and allmulticast Rx modes Yanling Song
2021-12-24 8:32 ` [PATCH v3 20/25] net/spnic: support flow control Yanling Song
2021-12-24 8:32 ` [PATCH v3 21/25] net/spnic: support getting Tx/Rx queues info Yanling Song
2021-12-24 8:32 ` [PATCH v3 22/25] net/spnic: net/spnic: support xstats statistics Yanling Song
2021-12-24 8:32 ` [PATCH v3 23/25] net/spnic: support VFIO interrupt Yanling Song
2021-12-24 8:32 ` [PATCH v3 24/25] net/spnic: support Tx/Rx queue start/stop Yanling Song
2021-12-24 8:32 ` [PATCH v3 25/25] net/spnic: add doc infrastructure Yanling Song
2021-12-24 17:44 ` [PATCH v3 00/25] Net/SPNIC: support SPNIC into DPDK 22.03 Stephen Hemminger
2021-12-28 7:01 ` Yanling Song
2021-12-28 15:55 ` Stephen Hemminger
2021-12-29 12:11 ` Yanling Song
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=efd5ae3b5108412d34a56a1de12e0e1e6f8f1f2a.1640332922.git.songyl@ramaxel.com \
--to=songyl@ramaxel.com \
--cc=dev@dpdk.org \
--cc=ferruh.yigit@intel.com \
--cc=xuyun@ramaxel.com \
--cc=yanggan@ramaxel.com \
--cc=yanling.song@linux.dev \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).