From: Yanling Song <songyl@ramaxel.com>
To: <dev@dpdk.org>
Cc: <songyl@ramaxel.com>, <yanling.song@linux.dev>,
<yanggan@ramaxel.com>, <ferruh.yigit@intel.com>
Subject: [PATCH v1 10/25] net/spnic: add function info initialization
Date: Sat, 18 Dec 2021 10:51:37 +0800 [thread overview]
Message-ID: <6015a42cf3bd56b453f47a284423877c0f490ab7.1639636621.git.songyl@ramaxel.com> (raw)
In-Reply-To: <cover.1639636621.git.songyl@ramaxel.com>
This patch mainly implements function info initialization
including mtu, link state, port state, port info and cos
as well as the definition of the corresponding data structure.
Signed-off-by: Yanling Song <songyl@ramaxel.com>
---
drivers/net/spnic/base/spnic_hw_cfg.c | 43 +++
drivers/net/spnic/base/spnic_hw_cfg.h | 6 +
drivers/net/spnic/base/spnic_nic_cfg.c | 221 ++++++++++++++
drivers/net/spnic/base/spnic_nic_cfg.h | 213 ++++++++++++++
drivers/net/spnic/spnic_ethdev.c | 382 ++++++++++++++++++++++++-
drivers/net/spnic/spnic_ethdev.h | 22 +-
6 files changed, 876 insertions(+), 11 deletions(-)
diff --git a/drivers/net/spnic/base/spnic_hw_cfg.c b/drivers/net/spnic/base/spnic_hw_cfg.c
index 6505f48273..49e16ee89c 100644
--- a/drivers/net/spnic/base/spnic_hw_cfg.c
+++ b/drivers/net/spnic/base/spnic_hw_cfg.c
@@ -156,6 +156,49 @@ void spnic_free_capability(void *dev)
rte_free(((struct spnic_hwdev *)dev)->cfg_mgmt);
}
+/* *
+ * @brief spnic_support_nic - function support nic
+ * @param hwdev: device pointer to hwdev
+ * @retval true: function support nic
+ * @retval false: function not support nic
+ */
+bool spnic_support_nic(void *hwdev)
+{
+ struct spnic_hwdev *dev = (struct spnic_hwdev *)hwdev;
+
+ if (!hwdev)
+ return false;
+
+ if (!IS_NIC_TYPE(dev))
+ return false;
+
+ return true;
+}
+
+u16 spnic_func_max_sqs(void *hwdev)
+{
+ struct spnic_hwdev *dev = hwdev;
+
+ if (!dev) {
+ PMD_DRV_LOG(INFO, "Hwdev is NULL for getting max_sqs");
+ return 0;
+ }
+
+ return dev->cfg_mgmt->svc_cap.nic_cap.max_sqs;
+}
+
+u16 spnic_func_max_rqs(void *hwdev)
+{
+ struct spnic_hwdev *dev = hwdev;
+
+ if (!dev) {
+ PMD_DRV_LOG(INFO, "Hwdev is NULL for getting max_rqs");
+ return 0;
+ }
+
+ return dev->cfg_mgmt->svc_cap.nic_cap.max_rqs;
+}
+
u8 spnic_physical_port_id(void *hwdev)
{
struct spnic_hwdev *dev = hwdev;
diff --git a/drivers/net/spnic/base/spnic_hw_cfg.h b/drivers/net/spnic/base/spnic_hw_cfg.h
index 9ab51f2875..5019f38ec2 100644
--- a/drivers/net/spnic/base/spnic_hw_cfg.h
+++ b/drivers/net/spnic/base/spnic_hw_cfg.h
@@ -112,8 +112,14 @@ struct spnic_cfg_cmd_dev_cap {
int spnic_init_capability(void *dev);
void spnic_free_capability(void *dev);
+u16 spnic_func_max_sqs(void *hwdev);
+u16 spnic_func_max_rqs(void *hwdev);
+
u8 spnic_physical_port_id(void *hwdev);
int cfg_mbx_vf_proc_msg(void *hwdev, void *pri_handle, u16 cmd, void *buf_in,
u16 in_size, void *buf_out, u16 *out_size);
+
+bool spnic_support_nic(void *hwdev);
+
#endif /* _SPNIC_HW_CFG_H_ */
diff --git a/drivers/net/spnic/base/spnic_nic_cfg.c b/drivers/net/spnic/base/spnic_nic_cfg.c
index c47bc330a3..886aaea384 100644
--- a/drivers/net/spnic/base/spnic_nic_cfg.c
+++ b/drivers/net/spnic/base/spnic_nic_cfg.c
@@ -265,6 +265,227 @@ int spnic_get_port_info(void *hwdev, struct nic_port_info *port_info)
return 0;
}
+
+int spnic_get_link_state(void *hwdev, u8 *link_state)
+{
+ struct spnic_cmd_link_state get_link;
+ u16 out_size = sizeof(get_link);
+ int err;
+
+ if (!hwdev || !link_state)
+ return -EINVAL;
+
+ memset(&get_link, 0, sizeof(get_link));
+ get_link.port_id = spnic_physical_port_id(hwdev);
+ err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_LINK_STATUS, &get_link,
+ sizeof(get_link), &get_link, &out_size);
+ if (err || !out_size || get_link.msg_head.status) {
+ PMD_DRV_LOG(ERR, "Get link state failed, err: %d, status: 0x%x, out size: 0x%x",
+ err, get_link.msg_head.status, out_size);
+ return -EIO;
+ }
+
+ *link_state = get_link.state;
+
+ return 0;
+}
+
+int spnic_set_vport_enable(void *hwdev, bool enable)
+{
+ struct spnic_vport_state en_state;
+ u16 out_size = sizeof(en_state);
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ memset(&en_state, 0, sizeof(en_state));
+ en_state.func_id = spnic_global_func_id(hwdev);
+ en_state.state = enable ? 1 : 0;
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_CMD_SET_VPORT_ENABLE, &en_state,
+ sizeof(en_state), &en_state, &out_size);
+ if (err || !out_size || en_state.msg_head.status) {
+ PMD_DRV_LOG(ERR, "Set vport state failed, err: %d, status: 0x%x, out size: 0x%x",
+ err, en_state.msg_head.status, out_size);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int spnic_set_port_enable(void *hwdev, bool enable)
+{
+ struct mag_cmd_set_port_enable en_state;
+ u16 out_size = sizeof(en_state);
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ if (spnic_func_type(hwdev) == TYPE_VF)
+ return 0;
+
+ memset(&en_state, 0, sizeof(en_state));
+ en_state.function_id = spnic_global_func_id(hwdev);
+ en_state.state = enable ? MAG_CMD_TX_ENABLE | MAG_CMD_RX_ENABLE :
+ MAG_CMD_PORT_DISABLE;
+
+ err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_SET_PORT_ENABLE, &en_state,
+ sizeof(en_state), &en_state, &out_size);
+ if (err || !out_size || en_state.head.status) {
+ PMD_DRV_LOG(ERR, "Set port state failed, err: %d, status: 0x%x, out size: 0x%x",
+ err, en_state.head.status, out_size);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int spnic_set_function_table(void *hwdev, u32 cfg_bitmap,
+ struct spnic_func_tbl_cfg *cfg)
+{
+ struct spnic_cmd_set_func_tbl cmd_func_tbl;
+ u16 out_size = sizeof(cmd_func_tbl);
+ int err;
+
+ memset(&cmd_func_tbl, 0, sizeof(cmd_func_tbl));
+ cmd_func_tbl.func_id = spnic_global_func_id(hwdev);
+ cmd_func_tbl.cfg_bitmap = cfg_bitmap;
+ cmd_func_tbl.tbl_cfg = *cfg;
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_CMD_SET_FUNC_TBL,
+ &cmd_func_tbl, sizeof(cmd_func_tbl),
+ &cmd_func_tbl, &out_size);
+ if (err || cmd_func_tbl.msg_head.status || !out_size) {
+ PMD_DRV_LOG(ERR, "Set func table failed, bitmap: 0x%x, err: %d, "
+ "status: 0x%x, out size: 0x%x\n", cfg_bitmap, err,
+ cmd_func_tbl.msg_head.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int spnic_init_function_table(void *hwdev, u16 rx_buff_len)
+{
+ struct spnic_func_tbl_cfg func_tbl_cfg;
+ u32 cfg_bitmap = BIT(FUNC_CFG_INIT) | BIT(FUNC_CFG_MTU) |
+ BIT(FUNC_CFG_RX_BUF_SIZE);
+
+ memset(&func_tbl_cfg, 0, sizeof(func_tbl_cfg));
+ func_tbl_cfg.mtu = 0x3FFF; /* Default, max mtu */
+ func_tbl_cfg.rx_wqe_buf_size = rx_buff_len;
+
+ return spnic_set_function_table(hwdev, cfg_bitmap, &func_tbl_cfg);
+}
+
+int spnic_set_port_mtu(void *hwdev, u16 new_mtu)
+{
+ struct spnic_func_tbl_cfg func_tbl_cfg;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ if (new_mtu < SPNIC_MIN_MTU_SIZE) {
+ PMD_DRV_LOG(ERR, "Invalid mtu size: %ubytes, mtu size < %ubytes",
+ new_mtu, SPNIC_MIN_MTU_SIZE);
+ return -EINVAL;
+ }
+
+ if (new_mtu > SPNIC_MAX_JUMBO_FRAME_SIZE) {
+ PMD_DRV_LOG(ERR, "Invalid mtu size: %ubytes, mtu size > %ubytes",
+ new_mtu, SPNIC_MAX_JUMBO_FRAME_SIZE);
+ return -EINVAL;
+ }
+
+ memset(&func_tbl_cfg, 0, sizeof(func_tbl_cfg));
+ func_tbl_cfg.mtu = new_mtu;
+
+ return spnic_set_function_table(hwdev, BIT(FUNC_CFG_MTU),
+ &func_tbl_cfg);
+}
+
+static int spnic_vf_func_init(void *hwdev)
+{
+ struct spnic_cmd_register_vf register_info;
+ u16 out_size = sizeof(register_info);
+ int err;
+
+ if (spnic_func_type(hwdev) != TYPE_VF)
+ return 0;
+
+ memset(®ister_info, 0, sizeof(register_info));
+ register_info.op_register = 1;
+ err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_CMD_VF_REGISTER,
+ ®ister_info, sizeof(register_info),
+ ®ister_info, &out_size);
+ if (err || register_info.msg_head.status || !out_size) {
+ PMD_DRV_LOG(ERR, "Register VF failed, err: %d, status: 0x%x, out size: 0x%x",
+ err, register_info.msg_head.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int spnic_vf_func_free(void *hwdev)
+{
+ struct spnic_cmd_register_vf unregister;
+ u16 out_size = sizeof(unregister);
+ int err;
+
+ if (spnic_func_type(hwdev) != TYPE_VF)
+ return 0;
+
+ memset(&unregister, 0, sizeof(unregister));
+ unregister.op_register = 0;
+ err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_CMD_VF_REGISTER,
+ &unregister, sizeof(unregister),
+ &unregister, &out_size);
+ if (err || unregister.msg_head.status || !out_size) {
+ PMD_DRV_LOG(ERR, "Unregister VF failed, err: %d, status: 0x%x, out size: 0x%x",
+ err, unregister.msg_head.status, out_size);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int spnic_init_nic_hwdev(void *hwdev)
+{
+ return spnic_vf_func_init(hwdev);
+}
+
+void spnic_free_nic_hwdev(void *hwdev)
+{
+ if (!hwdev)
+ return;
+
+ spnic_vf_func_free(hwdev);
+}
+
+int spnic_vf_get_default_cos(void *hwdev, u8 *cos_id)
+{
+ struct spnic_cmd_vf_dcb_state vf_dcb;
+ u16 out_size = sizeof(vf_dcb);
+ int err;
+
+ memset(&vf_dcb, 0, sizeof(vf_dcb));
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_CMD_VF_COS, &vf_dcb,
+ sizeof(vf_dcb), &vf_dcb, &out_size);
+ if (err || !out_size || vf_dcb.msg_head.status) {
+ PMD_DRV_LOG(ERR, "Get VF default cos failed, err: %d, status: 0x%x, out size: 0x%x",
+ err, vf_dcb.msg_head.status, out_size);
+ return -EIO;
+ }
+
+ *cos_id = vf_dcb.state.default_cos;
+
+ return 0;
+}
+
static int _mag_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in,
u16 in_size, void *buf_out, u16 *out_size)
{
diff --git a/drivers/net/spnic/base/spnic_nic_cfg.h b/drivers/net/spnic/base/spnic_nic_cfg.h
index 669e982876..98cad645d2 100644
--- a/drivers/net/spnic/base/spnic_nic_cfg.h
+++ b/drivers/net/spnic/base/spnic_nic_cfg.h
@@ -12,6 +12,26 @@
#define OS_VF_ID_TO_HW(os_vf_id) ((os_vf_id) + 1)
#define HW_VF_ID_TO_OS(hw_vf_id) ((hw_vf_id) - 1)
+#define SPNIC_DCB_UP_MAX 0x8
+
+#define SPNIC_MAX_NUM_RQ 256
+
+#define SPNIC_MAX_MTU_SIZE 9600
+#define SPNIC_MIN_MTU_SIZE 384
+
+#define SPNIC_COS_NUM_MAX 8
+
+#define SPNIC_VLAN_TAG_SIZE 4
+#define SPNIC_ETH_OVERHEAD \
+ (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + SPNIC_VLAN_TAG_SIZE * 2)
+
+#define SPNIC_MIN_FRAME_SIZE (SPNIC_MIN_MTU_SIZE + SPNIC_ETH_OVERHEAD)
+#define SPNIC_MAX_JUMBO_FRAME_SIZE (SPNIC_MAX_MTU_SIZE + SPNIC_ETH_OVERHEAD)
+
+#define SPNIC_MTU_TO_PKTLEN(mtu) ((mtu) + SPNIC_ETH_OVERHEAD)
+
+#define SPNIC_PKTLEN_TO_MTU(pktlen) ((pktlen) - SPNIC_ETH_OVERHEAD)
+
#define SPNIC_PF_SET_VF_ALREADY 0x4
#define SPNIC_MGMT_STATUS_EXIST 0x6
#define CHECK_IPSU_15BIT 0x8000
@@ -92,6 +112,114 @@ struct spnic_cmd_link_state {
u16 rsvd1;
};
+struct nic_pause_config {
+ u8 auto_neg;
+ u8 rx_pause;
+ u8 tx_pause;
+};
+
+struct spnic_cmd_pause_config {
+ struct mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 opcode;
+ u16 rsvd1;
+ u8 auto_neg;
+ u8 rx_pause;
+ u8 tx_pause;
+ u8 rsvd2[5];
+};
+
+struct spnic_vport_state {
+ struct mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+ u8 state; /* 0--disable, 1--enable */
+ u8 rsvd2[3];
+};
+
+#define MAG_CMD_PORT_DISABLE 0x0
+#define MAG_CMD_TX_ENABLE 0x1
+#define MAG_CMD_RX_ENABLE 0x2
+/* the physical port is disable only when all pf of the port are set to down,
+ * if any pf is enable, the port is enable
+ */
+struct mag_cmd_set_port_enable {
+ struct mgmt_msg_head head;
+
+ u16 function_id;
+ u16 rsvd0;
+
+ u8 state; /* bitmap bit0:tx_en bit1:rx_en */
+ u8 rsvd1[3];
+};
+
+struct mag_cmd_get_port_enable {
+ struct mgmt_msg_head head;
+
+ u8 port;
+ u8 state; /* bitmap bit0:tx_en bit1:rx_en */
+ u8 rsvd0[2];
+};
+
+struct spnic_cmd_clear_qp_resource {
+ struct mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+};
+
+
+enum spnic_func_tbl_cfg_bitmap {
+ FUNC_CFG_INIT,
+ FUNC_CFG_RX_BUF_SIZE,
+ FUNC_CFG_MTU,
+};
+
+struct spnic_func_tbl_cfg {
+ u16 rx_wqe_buf_size;
+ u16 mtu;
+ u32 rsvd[9];
+};
+
+struct spnic_cmd_set_func_tbl {
+ struct mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd;
+
+ u32 cfg_bitmap;
+ struct spnic_func_tbl_cfg tbl_cfg;
+};
+
+enum {
+ SPNIC_IFLA_VF_LINK_STATE_AUTO, /* Link state of the uplink */
+ SPNIC_IFLA_VF_LINK_STATE_ENABLE, /* Link always up */
+ SPNIC_IFLA_VF_LINK_STATE_DISABLE, /* Link always down */
+};
+
+struct spnic_dcb_state {
+ u8 dcb_on;
+ u8 default_cos;
+ u16 rsvd1;
+ u8 up_cos[SPNIC_DCB_UP_MAX];
+ u32 rsvd2[7];
+};
+
+struct spnic_cmd_vf_dcb_state {
+ struct mgmt_msg_head msg_head;
+
+ struct spnic_dcb_state state;
+};
+
+struct spnic_cmd_register_vf {
+ struct mgmt_msg_head msg_head;
+
+ u8 op_register; /* 0 - unregister, 1 - register */
+ u8 rsvd[39];
+};
+
int l2nic_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size,
void *buf_out, u16 *out_size);
@@ -164,6 +292,77 @@ int spnic_set_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id);
*/
int spnic_del_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id);
+/**
+ * Set function mtu
+ *
+ * @param[in] hwdev
+ * Device pointer to hwdev
+ * @param[in] new_mtu
+ * MTU value
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_set_port_mtu(void *hwdev, u16 new_mtu);
+
+/**
+ * Set function valid status
+ *
+ * @param[in] hwdev
+ * Device pointer to hwdev
+ * @param[in] enable
+ * 0-disable, 1-enable
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_set_vport_enable(void *hwdev, bool enable);
+
+/**
+ * Set port status
+ *
+ * @param[in] hwdev
+ * Device pointer to hwdev
+ * @param[in] enable
+ * 0-disable, 1-enable
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_set_port_enable(void *hwdev, bool enable);
+
+/**
+ * Get link state
+ *
+ * @param[in] hwdev
+ * Device pointer to hwdev
+ * @param[out] link_state
+ * Link state, 0-link down, 1-link up
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_get_link_state(void *hwdev, u8 *link_state);
+
+/**
+ * Init nic hwdev
+ *
+ * @param[in] hwdev
+ * Device pointer to hwdev
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_init_nic_hwdev(void *hwdev);
+
+/**
+ * Free nic hwdev
+ *
+ * @param[in] hwdev
+ * Device pointer to hwdev
+ */
+void spnic_free_nic_hwdev(void *hwdev);
+
/**
* Get port info
*
@@ -177,4 +376,18 @@ int spnic_del_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id);
*/
int spnic_get_port_info(void *hwdev, struct nic_port_info *port_info);
+int spnic_init_function_table(void *hwdev, u16 rx_buff_len);
+
+/**
+ * Get VF function default cos
+ *
+ * @param[in] hwdev
+ * Device pointer to hwdev
+ * @param[out] cos_id
+ * Cos id
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_vf_get_default_cos(void *hwdev, u8 *cos_id);
#endif /* _SPNIC_NIC_CFG_H_ */
diff --git a/drivers/net/spnic/spnic_ethdev.c b/drivers/net/spnic/spnic_ethdev.c
index 8f71280fa7..7f73e70df1 100644
--- a/drivers/net/spnic/spnic_ethdev.c
+++ b/drivers/net/spnic/spnic_ethdev.c
@@ -30,23 +30,106 @@ int spnic_logtype;
#define SPNIC_MAX_UC_MAC_ADDRS 128
#define SPNIC_MAX_MC_MAC_ADDRS 128
-static void spnic_delete_mc_addr_list(struct spnic_nic_dev *nic_dev)
+/**
+ * Deinit mac_vlan table in hardware.
+ *
+ * @param[in] eth_dev
+ * Pointer to ethernet device structure.
+ */
+
+/**
+ * Set ethernet device link state up.
+ *
+ * @param[in] dev
+ * Pointer to ethernet device structure.
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure.
+ */
+static int spnic_dev_set_link_up(struct rte_eth_dev *dev)
{
- u16 func_id;
- u32 i;
+ struct spnic_nic_dev *nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+ int err;
- func_id = spnic_global_func_id(nic_dev->hwdev);
+ /* Link status follow phy port status, mpu will open pma */
+ err = spnic_set_port_enable(nic_dev->hwdev, true);
+ if (err)
+ PMD_DRV_LOG(ERR, "Set MAC link up failed, dev_name: %s, port_id: %d",
+ nic_dev->dev_name, dev->data->port_id);
- for (i = 0; i < SPNIC_MAX_MC_MAC_ADDRS; i++) {
- if (rte_is_zero_ether_addr(&nic_dev->mc_list[i]))
+ return err;
+}
+
+/**
+ * Set ethernet device link state down.
+ *
+ * @param[in] dev
+ * Pointer to ethernet device structure.
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure.
+ */
+static int spnic_dev_set_link_down(struct rte_eth_dev *dev)
+{
+ struct spnic_nic_dev *nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+ int err;
+
+ /* Link status follow phy port status, mpu will close pma */
+ err = spnic_set_port_enable(nic_dev->hwdev, false);
+ if (err)
+ PMD_DRV_LOG(ERR, "Set MAC link down failed, dev_name: %s, port_id: %d",
+ nic_dev->dev_name, dev->data->port_id);
+
+ return err;
+}
+
+/**
+ * Get device physical link information.
+ *
+ * @param[in] dev
+ * Pointer to ethernet device structure.
+ * @param[in] wait_to_complete
+ * Wait for request completion.
+ *
+ * @retval 0 : Link status changed
+ * @retval -1 : Link status not changed.
+ */
+static int spnic_link_update(struct rte_eth_dev *dev, int wait_to_complete)
+{
+#define CHECK_INTERVAL 10 /* 10ms */
+#define MAX_REPEAT_TIME 100 /* 1s (100 * 10ms) in total */
+ struct spnic_nic_dev *nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+ struct rte_eth_link link;
+ u8 link_state;
+ unsigned int rep_cnt = MAX_REPEAT_TIME;
+ int ret;
+
+ memset(&link, 0, sizeof(link));
+ do {
+ /* Get link status information from hardware */
+ ret = spnic_get_link_state(nic_dev->hwdev, &link_state);
+ if (ret) {
+ link.link_status = ETH_LINK_DOWN;
+ link.link_speed = ETH_SPEED_NUM_NONE;
+ link.link_duplex = ETH_LINK_HALF_DUPLEX;
+ link.link_autoneg = ETH_LINK_FIXED;
+ goto out;
+ }
+
+ get_port_info(nic_dev->hwdev, link_state, &link);
+
+ if (!wait_to_complete || link.link_status)
break;
- spnic_del_mac(nic_dev->hwdev, nic_dev->mc_list[i].addr_bytes,
- 0, func_id);
- memset(&nic_dev->mc_list[i], 0, sizeof(struct rte_ether_addr));
- }
+ rte_delay_ms(CHECK_INTERVAL);
+ } while (rep_cnt--);
+
+out:
+ return rte_eth_linkstatus_set(dev, &link);
}
+static void spnic_delete_mc_addr_list(struct spnic_nic_dev *nic_dev);
+
/**
* Deinit mac_vlan table in hardware.
*
@@ -82,6 +165,122 @@ static void spnic_deinit_mac_addr(struct rte_eth_dev *eth_dev)
spnic_delete_mc_addr_list(nic_dev);
}
+static int spnic_init_sw_rxtxqs(struct spnic_nic_dev *nic_dev)
+{
+ u32 txq_size;
+ u32 rxq_size;
+
+ /* Allocate software txq array */
+ txq_size = nic_dev->max_sqs * sizeof(*nic_dev->txqs);
+ nic_dev->txqs = rte_zmalloc("spnic_txqs", txq_size,
+ RTE_CACHE_LINE_SIZE);
+ if (!nic_dev->txqs) {
+ PMD_DRV_LOG(ERR, "Allocate txqs failed");
+ return -ENOMEM;
+ }
+
+ /* Allocate software rxq array */
+ rxq_size = nic_dev->max_rqs * sizeof(*nic_dev->rxqs);
+ nic_dev->rxqs = rte_zmalloc("spnic_rxqs", rxq_size,
+ RTE_CACHE_LINE_SIZE);
+ if (!nic_dev->rxqs) {
+ /* Free txqs */
+ rte_free(nic_dev->txqs);
+ nic_dev->txqs = NULL;
+
+ PMD_DRV_LOG(ERR, "Allocate rxqs failed");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void spnic_deinit_sw_rxtxqs(struct spnic_nic_dev *nic_dev)
+{
+ rte_free(nic_dev->txqs);
+ nic_dev->txqs = NULL;
+
+ rte_free(nic_dev->rxqs);
+ nic_dev->rxqs = NULL;
+}
+
+/**
+ * Start the device.
+ *
+ * Initialize function table, rxq and txq context, config rx offload, and enable
+ * vport and port to prepare receiving packets.
+ *
+ * @param[in] eth_dev
+ * Pointer to ethernet device structure.
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+static int spnic_dev_start(struct rte_eth_dev *eth_dev)
+{
+ struct spnic_nic_dev *nic_dev;
+ int err;
+
+ nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
+
+ err = spnic_init_function_table(nic_dev->hwdev, nic_dev->rx_buff_len);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Init function table failed, dev_name: %s",
+ eth_dev->data->name);
+ goto init_func_tbl_fail;
+ }
+
+ /* Set default mtu */
+ err = spnic_set_port_mtu(nic_dev->hwdev, nic_dev->mtu_size);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Set mtu_size[%d] failed, dev_name: %s",
+ nic_dev->mtu_size, eth_dev->data->name);
+ 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);
+
+ rte_bit_relaxed_set32(SPNIC_DEV_START, &nic_dev->dev_status);
+
+ return 0;
+
+set_mtu_fail:
+init_func_tbl_fail:
+
+ return err;
+}
+
+/**
+ * Stop the device.
+ *
+ * Stop phy port and vport, flush pending io request, clean context configure
+ * and free io resourece.
+ *
+ * @param[in] dev
+ * Pointer to ethernet device structure.
+ */
+static int spnic_dev_stop(struct rte_eth_dev *dev)
+{
+ struct spnic_nic_dev *nic_dev;
+ struct rte_eth_link link;
+
+ nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+ if (!rte_bit_relaxed_test_and_clear32(SPNIC_DEV_START, &nic_dev->dev_status)) {
+ PMD_DRV_LOG(INFO, "Device %s already stopped",
+ nic_dev->dev_name);
+ return 0;
+ }
+
+ /* Clear recorded link status */
+ memset(&link, 0, sizeof(link));
+ (void)rte_eth_linkstatus_set(dev, &link);
+
+ return 0;
+}
+
/**
* Close the device.
*
@@ -99,11 +298,19 @@ static int spnic_dev_close(struct rte_eth_dev *eth_dev)
return 0;
}
+ spnic_dev_stop(eth_dev);
+
+ spnic_deinit_sw_rxtxqs(nic_dev);
spnic_deinit_mac_addr(eth_dev);
rte_free(nic_dev->mc_list);
rte_bit_relaxed_clear32(SPNIC_DEV_INTR_EN, &nic_dev->dev_status);
+
+ /* Destroy rx mode mutex */
+ spnic_mutex_destroy(&nic_dev->rx_mode_mutex);
+
+ spnic_free_nic_hwdev(nic_dev->hwdev);
spnic_free_hwdev(nic_dev->hwdev);
eth_dev->dev_ops = NULL;
@@ -113,6 +320,34 @@ static int spnic_dev_close(struct rte_eth_dev *eth_dev)
return 0;
}
+
+static int spnic_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
+{
+ struct spnic_nic_dev *nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+ int err = 0;
+
+ PMD_DRV_LOG(INFO, "Set port mtu, port_id: %d, mtu: %d, max_pkt_len: %d",
+ dev->data->port_id, mtu, SPNIC_MTU_TO_PKTLEN(mtu));
+
+ if (mtu < SPNIC_MIN_MTU_SIZE || mtu > SPNIC_MAX_MTU_SIZE) {
+ PMD_DRV_LOG(ERR, "Invalid mtu: %d, must between %d and %d",
+ mtu, SPNIC_MIN_MTU_SIZE, SPNIC_MAX_MTU_SIZE);
+ return -EINVAL;
+ }
+
+ err = spnic_set_port_mtu(nic_dev->hwdev, mtu);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Set port mtu failed, err: %d", err);
+ return err;
+ }
+
+ /* Update max frame size */
+ dev->data->dev_conf.rxmode.mtu = SPNIC_MTU_TO_PKTLEN(mtu);
+ nic_dev->mtu_size = mtu;
+
+ return err;
+}
+
/**
* Update MAC address
*
@@ -233,6 +468,23 @@ static int spnic_mac_addr_add(struct rte_eth_dev *dev,
return 0;
}
+static void spnic_delete_mc_addr_list(struct spnic_nic_dev *nic_dev)
+{
+ u16 func_id;
+ u32 i;
+
+ func_id = spnic_global_func_id(nic_dev->hwdev);
+
+ for (i = 0; i < SPNIC_MAX_MC_MAC_ADDRS; i++) {
+ if (rte_is_zero_ether_addr(&nic_dev->mc_list[i]))
+ break;
+
+ spnic_del_mac(nic_dev->hwdev, nic_dev->mc_list[i].addr_bytes,
+ 0, func_id);
+ memset(&nic_dev->mc_list[i], 0, sizeof(struct rte_ether_addr));
+ }
+}
+
/**
* Set multicast MAC address
*
@@ -287,7 +539,15 @@ static int spnic_set_mc_addr_list(struct rte_eth_dev *dev,
return 0;
}
+
static const struct eth_dev_ops spnic_pmd_ops = {
+ .dev_set_link_up = spnic_dev_set_link_up,
+ .dev_set_link_down = spnic_dev_set_link_down,
+ .link_update = spnic_link_update,
+ .dev_start = spnic_dev_start,
+ .dev_stop = spnic_dev_stop,
+ .dev_close = spnic_dev_close,
+ .mtu_set = spnic_dev_set_mtu,
.mac_addr_set = spnic_set_mac_addr,
.mac_addr_remove = spnic_mac_addr_remove,
.mac_addr_add = spnic_mac_addr_add,
@@ -295,6 +555,11 @@ static const struct eth_dev_ops spnic_pmd_ops = {
};
static const struct eth_dev_ops spnic_pmd_vf_ops = {
+ .link_update = spnic_link_update,
+ .dev_start = spnic_dev_start,
+ .dev_stop = spnic_dev_stop,
+ .dev_close = spnic_dev_close,
+ .mtu_set = spnic_dev_set_mtu,
.mac_addr_set = spnic_set_mac_addr,
.mac_addr_remove = spnic_mac_addr_remove,
.mac_addr_add = spnic_mac_addr_add,
@@ -341,6 +606,66 @@ static int spnic_init_mac_table(struct rte_eth_dev *eth_dev)
return 0;
}
+static int spnic_pf_get_default_cos(struct spnic_hwdev *hwdev, u8 *cos_id)
+{
+ u8 default_cos = 0;
+ u8 valid_cos_bitmap;
+ u8 i;
+
+ valid_cos_bitmap = hwdev->cfg_mgmt->svc_cap.cos_valid_bitmap;
+ if (!valid_cos_bitmap) {
+ PMD_DRV_LOG(ERR, "PF has none cos to support\n");
+ return -EFAULT;
+ }
+
+ for (i = 0; i < SPNIC_COS_NUM_MAX; i++) {
+ if (valid_cos_bitmap & BIT(i))
+ /* Find max cos id as default cos */
+ default_cos = i;
+ }
+
+ *cos_id = default_cos;
+
+ return 0;
+}
+
+static int spnic_init_default_cos(struct spnic_nic_dev *nic_dev)
+{
+ u8 cos_id = 0;
+ int err;
+
+ if (!SPNIC_IS_VF(nic_dev->hwdev)) {
+ err = spnic_pf_get_default_cos(nic_dev->hwdev, &cos_id);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Get PF default cos failed, err: %d",
+ err);
+ return err;
+ }
+ } else {
+ err = spnic_vf_get_default_cos(nic_dev->hwdev, &cos_id);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Get VF default cos failed, err: %d",
+ err);
+ return err;
+ }
+ }
+
+ nic_dev->default_cos = cos_id;
+ PMD_DRV_LOG(INFO, "Default cos %d", nic_dev->default_cos);
+ return 0;
+}
+
+static int spnic_set_default_hw_feature(struct spnic_nic_dev *nic_dev)
+{
+ int err;
+
+ err = spnic_init_default_cos(nic_dev);
+ if (err)
+ return err;
+
+ return 0;
+}
+
static int spnic_func_init(struct rte_eth_dev *eth_dev)
{
struct spnic_nic_dev *nic_dev = NULL;
@@ -411,10 +736,28 @@ static int spnic_func_init(struct rte_eth_dev *eth_dev)
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);
+
if (SPNIC_FUNC_TYPE(nic_dev->hwdev) == TYPE_VF)
eth_dev->dev_ops = &spnic_pmd_vf_ops;
else
eth_dev->dev_ops = &spnic_pmd_ops;
+
+ err = spnic_init_nic_hwdev(nic_dev->hwdev);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Init nic hwdev failed, dev_name: %s",
+ eth_dev->data->name);
+ goto init_nic_hwdev_fail;
+ }
+
+ err = spnic_init_sw_rxtxqs(nic_dev);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Init sw rxqs or txqs failed, dev_name: %s",
+ eth_dev->data->name);
+ goto init_sw_rxtxqs_fail;
+ }
+
err = spnic_init_mac_table(eth_dev);
if (err) {
PMD_DRV_LOG(ERR, "Init mac table failed, dev_name: %s",
@@ -422,6 +765,16 @@ static int spnic_func_init(struct rte_eth_dev *eth_dev)
goto init_mac_table_fail;
}
+ /* Set hardware feature to default status */
+ err = spnic_set_default_hw_feature(nic_dev);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Set hw default features failed, dev_name: %s",
+ eth_dev->data->name);
+ goto set_default_feature_fail;
+ }
+
+ spnic_mutex_init(&nic_dev->rx_mode_mutex, NULL);
+
rte_bit_relaxed_set32(SPNIC_DEV_INTR_EN, &nic_dev->dev_status);
rte_bit_relaxed_set32(SPNIC_DEV_INIT, &nic_dev->dev_status);
@@ -430,7 +783,16 @@ static int spnic_func_init(struct rte_eth_dev *eth_dev)
return 0;
+set_default_feature_fail:
+ spnic_deinit_mac_addr(eth_dev);
+
init_mac_table_fail:
+ spnic_deinit_sw_rxtxqs(nic_dev);
+
+init_sw_rxtxqs_fail:
+ spnic_free_nic_hwdev(nic_dev->hwdev);
+
+init_nic_hwdev_fail:
spnic_free_hwdev(nic_dev->hwdev);
eth_dev->dev_ops = NULL;
diff --git a/drivers/net/spnic/spnic_ethdev.h b/drivers/net/spnic/spnic_ethdev.h
index 654234aaa4..321db389dc 100644
--- a/drivers/net/spnic/spnic_ethdev.h
+++ b/drivers/net/spnic/spnic_ethdev.h
@@ -4,6 +4,7 @@
#ifndef _SPNIC_ETHDEV_H_
#define _SPNIC_ETHDEV_H_
+#define SPNIC_DEV_NAME_LEN 32
#define SPNIC_UINT32_BIT_SIZE (CHAR_BIT * sizeof(uint32_t))
#define SPNIC_VFTA_SIZE (4096 / SPNIC_UINT32_BIT_SIZE)
@@ -16,7 +17,25 @@ enum spnic_dev_status {
SPNIC_DEV_INTR_EN
};
-#define SPNIC_DEV_NAME_LEN 32
+enum nic_feature_cap {
+ NIC_F_CSUM = BIT(0),
+ NIC_F_SCTP_CRC = BIT(1),
+ NIC_F_TSO = BIT(2),
+ NIC_F_LRO = BIT(3),
+ NIC_F_UFO = BIT(4),
+ NIC_F_RSS = BIT(5),
+ NIC_F_RX_VLAN_FILTER = BIT(6),
+ NIC_F_RX_VLAN_STRIP = BIT(7),
+ NIC_F_TX_VLAN_INSERT = BIT(8),
+ NIC_F_VXLAN_OFFLOAD = BIT(9),
+ NIC_F_IPSEC_OFFLOAD = BIT(10),
+ NIC_F_FDIR = BIT(11),
+ NIC_F_PROMISC = BIT(12),
+ NIC_F_ALLMULTI = BIT(13),
+};
+
+#define DEFAULT_DRV_FEATURE 0x3FFF
+
struct spnic_nic_dev {
struct spnic_hwdev *hwdev; /* Hardware device */
@@ -53,6 +72,7 @@ struct spnic_nic_dev {
struct rte_ether_addr *mc_list;
char dev_name[SPNIC_DEV_NAME_LEN];
+ u64 feature_cap;
u32 vfta[SPNIC_VFTA_SIZE]; /* VLAN bitmap */
};
--
2.27.0
next prev parent reply other threads:[~2021-12-18 2:53 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-18 2:51 [PATCH v1 00/25] Net/SPNIC: support SPNIC into DPDK 22.03 Yanling Song
2021-12-18 2:51 ` [PATCH v1 01/25] drivers/net: introduce a new PMD driver Yanling Song
2021-12-19 19:40 ` Stephen Hemminger
2021-12-22 0:54 ` Yanling Song
2021-12-22 16:55 ` Stephen Hemminger
2021-12-23 8:10 ` Yanling Song
2021-12-18 2:51 ` [PATCH v1 02/25] net/spnic: initialize the HW interface Yanling Song
2021-12-18 2:51 ` [PATCH v1 03/25] net/spnic: add mbox message channel Yanling Song
2021-12-18 2:51 ` [PATCH v1 04/25] net/spnic: introduce event queue Yanling Song
2021-12-18 2:51 ` [PATCH v1 05/25] net/spnic: add mgmt module Yanling Song
2021-12-18 2:51 ` [PATCH v1 06/25] net/spnic: add cmdq and work queue Yanling Song
2021-12-18 2:51 ` [PATCH v1 07/25] net/spnic: add interface handling cmdq message Yanling Song
2021-12-18 2:51 ` [PATCH v1 08/25] net/spnic: add hardware info initialization Yanling Song
2021-12-18 2:51 ` [PATCH v1 09/25] net/spnic: support MAC and link event handling Yanling Song
2021-12-18 2:51 ` Yanling Song [this message]
2021-12-18 2:51 ` [PATCH v1 11/25] net/spnic: add queue pairs context initialization Yanling Song
2021-12-18 2:51 ` [PATCH v1 12/25] net/spnic: support mbuf handling of Tx/Rx Yanling Song
2021-12-18 2:51 ` [PATCH v1 13/25] net/spnic: support Rx congfiguration Yanling Song
2021-12-18 2:51 ` [PATCH v1 14/25] net/spnic: add port/vport enable Yanling Song
2021-12-18 2:51 ` [PATCH v1 15/25] net/spnic: support IO packets handling Yanling Song
2021-12-18 2:51 ` [PATCH v1 16/25] net/spnic: add device configure/version/info Yanling Song
2021-12-20 0:23 ` Stephen Hemminger
2021-12-22 0:56 ` Yanling Song
2021-12-18 2:51 ` [PATCH v1 17/25] net/spnic: support RSS configuration update and get Yanling Song
2021-12-18 2:51 ` [PATCH v1 18/25] net/spnic: support VLAN filtering and offloading Yanling Song
2021-12-18 2:51 ` [PATCH v1 19/25] net/spnic: support promiscuous and allmulticast Rx modes Yanling Song
2021-12-18 2:51 ` [PATCH v1 20/25] net/spnic: support flow control Yanling Song
2021-12-18 2:51 ` [PATCH v1 21/25] net/spnic: support getting Tx/Rx queues info Yanling Song
2021-12-18 2:51 ` [PATCH v1 22/25] net/spnic: net/spnic: support xstats statistics Yanling Song
2021-12-18 2:51 ` [PATCH v1 23/25] net/spnic: support VFIO interrupt Yanling Song
2021-12-18 2:51 ` [PATCH v1 24/25] net/spnic: support Tx/Rx queue start/stop Yanling Song
2021-12-18 2:51 ` [PATCH v1 25/25] net/spnic: add doc infrastructure 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=6015a42cf3bd56b453f47a284423877c0f490ab7.1639636621.git.songyl@ramaxel.com \
--to=songyl@ramaxel.com \
--cc=dev@dpdk.org \
--cc=ferruh.yigit@intel.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).