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 09/25] net/spnic: support MAC and link event handling
Date: Sat, 18 Dec 2021 10:51:36 +0800 [thread overview]
Message-ID: <2bdd398a489d626cf86b62f169bfa366a50f0afa.1639636621.git.songyl@ramaxel.com> (raw)
In-Reply-To: <cover.1639636621.git.songyl@ramaxel.com>
This commit adds interfaces to add/remove MAC addresses
and registers related ops to struct eth_dev_ops. Furthermore,
this commit adds callback to handle link events.
Signed-off-by: Yanling Song <songyl@ramaxel.com>
---
drivers/net/spnic/base/meson.build | 3 +-
drivers/net/spnic/base/spnic_hw_cfg.c | 12 +
drivers/net/spnic/base/spnic_hw_cfg.h | 2 +
drivers/net/spnic/base/spnic_nic_cfg.c | 291 +++++++++++++++++++
drivers/net/spnic/base/spnic_nic_cfg.h | 180 ++++++++++++
drivers/net/spnic/base/spnic_nic_event.c | 27 +-
drivers/net/spnic/base/spnic_nic_event.h | 9 +-
drivers/net/spnic/spnic_ethdev.c | 348 ++++++++++++++++++++++-
8 files changed, 861 insertions(+), 11 deletions(-)
create mode 100644 drivers/net/spnic/base/spnic_nic_cfg.c
create mode 100644 drivers/net/spnic/base/spnic_nic_cfg.h
diff --git a/drivers/net/spnic/base/meson.build b/drivers/net/spnic/base/meson.build
index 77a56ca41e..f4bb4469ae 100644
--- a/drivers/net/spnic/base/meson.build
+++ b/drivers/net/spnic/base/meson.build
@@ -11,7 +11,8 @@ sources = [
'spnic_cmdq.c',
'spnic_hw_comm.c',
'spnic_wq.c',
- 'spnic_hw_cfg.c'
+ 'spnic_hw_cfg.c',
+ 'spnic_nic_cfg.c'
]
extra_flags = []
diff --git a/drivers/net/spnic/base/spnic_hw_cfg.c b/drivers/net/spnic/base/spnic_hw_cfg.c
index e8856ce9fe..6505f48273 100644
--- a/drivers/net/spnic/base/spnic_hw_cfg.c
+++ b/drivers/net/spnic/base/spnic_hw_cfg.c
@@ -155,3 +155,15 @@ void spnic_free_capability(void *dev)
{
rte_free(((struct spnic_hwdev *)dev)->cfg_mgmt);
}
+
+u8 spnic_physical_port_id(void *hwdev)
+{
+ struct spnic_hwdev *dev = hwdev;
+
+ if (!dev) {
+ PMD_DRV_LOG(INFO, "Hwdev is NULL for getting physical port id");
+ return 0;
+ }
+
+ return dev->cfg_mgmt->svc_cap.port_id;
+}
diff --git a/drivers/net/spnic/base/spnic_hw_cfg.h b/drivers/net/spnic/base/spnic_hw_cfg.h
index 1b1b598726..9ab51f2875 100644
--- a/drivers/net/spnic/base/spnic_hw_cfg.h
+++ b/drivers/net/spnic/base/spnic_hw_cfg.h
@@ -112,6 +112,8 @@ struct spnic_cfg_cmd_dev_cap {
int spnic_init_capability(void *dev);
void spnic_free_capability(void *dev);
+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);
#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
new file mode 100644
index 0000000000..c47bc330a3
--- /dev/null
+++ b/drivers/net/spnic/base/spnic_nic_cfg.c
@@ -0,0 +1,291 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#include <rte_ether.h>
+#include "spnic_compat.h"
+#include "spnic_cmd.h"
+#include "spnic_mgmt.h"
+#include "spnic_hwif.h"
+#include "spnic_mbox.h"
+#include "spnic_hwdev.h"
+#include "spnic_wq.h"
+#include "spnic_cmdq.h"
+#include "spnic_nic_cfg.h"
+#include "spnic_hw_cfg.h"
+
+struct vf_msg_handler {
+ u16 cmd;
+};
+
+const struct vf_msg_handler vf_cmd_handler[] = {
+ {
+ .cmd = SPNIC_CMD_VF_REGISTER,
+ },
+
+ {
+ .cmd = SPNIC_CMD_GET_MAC,
+ },
+
+ {
+ .cmd = SPNIC_CMD_SET_MAC,
+ },
+
+ {
+ .cmd = SPNIC_CMD_DEL_MAC,
+ },
+
+ {
+ .cmd = SPNIC_CMD_UPDATE_MAC,
+ },
+
+ {
+ .cmd = SPNIC_CMD_VF_COS,
+ },
+};
+
+static const struct vf_msg_handler vf_mag_cmd_handler[] = {
+ {
+ .cmd = MAG_CMD_GET_LINK_STATUS,
+ },
+};
+
+static int mag_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size);
+
+int l2nic_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ u32 i, cmd_cnt = ARRAY_LEN(vf_cmd_handler);
+ bool cmd_to_pf = false;
+
+ if (spnic_func_type(hwdev) == TYPE_VF) {
+ for (i = 0; i < cmd_cnt; i++) {
+ if (cmd == vf_cmd_handler[i].cmd)
+ cmd_to_pf = true;
+ }
+ }
+
+ if (cmd_to_pf) {
+ return spnic_mbox_to_pf(hwdev, SPNIC_MOD_L2NIC, cmd, buf_in,
+ in_size, buf_out, out_size, 0);
+ }
+
+ return spnic_msg_to_mgmt_sync(hwdev, SPNIC_MOD_L2NIC, cmd, buf_in,
+ in_size, buf_out, out_size, 0);
+}
+
+static int spnic_check_mac_info(u8 status, u16 vlan_id)
+{
+ if ((status && status != SPNIC_MGMT_STATUS_EXIST &&
+ status != SPNIC_PF_SET_VF_ALREADY) ||
+ (vlan_id & CHECK_IPSU_15BIT &&
+ status == SPNIC_MGMT_STATUS_EXIST))
+ return -EINVAL;
+
+ return 0;
+}
+
+#define VLAN_N_VID 4096
+
+int spnic_set_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id)
+{
+ struct spnic_port_mac_set mac_info;
+ u16 out_size = sizeof(mac_info);
+ int err;
+
+ if (!hwdev || !mac_addr)
+ return -EINVAL;
+
+ memset(&mac_info, 0, sizeof(mac_info));
+
+ if (vlan_id >= VLAN_N_VID) {
+ PMD_DRV_LOG(ERR, "Invalid VLAN number: %d", vlan_id);
+ return -EINVAL;
+ }
+
+ mac_info.func_id = func_id;
+ mac_info.vlan_id = vlan_id;
+ memmove(mac_info.mac, mac_addr, ETH_ALEN);
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_CMD_SET_MAC, &mac_info,
+ sizeof(mac_info), &mac_info, &out_size);
+ if (err || !out_size ||
+ spnic_check_mac_info(mac_info.msg_head.status, mac_info.vlan_id)) {
+ PMD_DRV_LOG(ERR, "Update MAC failed, err: %d, status: 0x%x, out size: 0x%x",
+ err, mac_info.msg_head.status, out_size);
+ return -EINVAL;
+ }
+
+ if (mac_info.msg_head.status == SPNIC_PF_SET_VF_ALREADY) {
+ PMD_DRV_LOG(WARNING, "PF has already set VF mac, Ignore set operation");
+ return SPNIC_PF_SET_VF_ALREADY;
+ }
+
+ if (mac_info.msg_head.status == SPNIC_MGMT_STATUS_EXIST) {
+ PMD_DRV_LOG(WARNING, "MAC is repeated. Ignore update operation");
+ return 0;
+ }
+
+ return 0;
+}
+
+int spnic_del_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id)
+{
+ struct spnic_port_mac_set mac_info;
+ u16 out_size = sizeof(mac_info);
+ int err;
+
+ if (!hwdev || !mac_addr)
+ return -EINVAL;
+
+ if (vlan_id >= VLAN_N_VID) {
+ PMD_DRV_LOG(ERR, "Invalid VLAN number: %d", vlan_id);
+ return -EINVAL;
+ }
+
+ memset(&mac_info, 0, sizeof(mac_info));
+ mac_info.func_id = func_id;
+ mac_info.vlan_id = vlan_id;
+ memmove(mac_info.mac, mac_addr, ETH_ALEN);
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_CMD_DEL_MAC, &mac_info,
+ sizeof(mac_info), &mac_info, &out_size);
+ if (err || !out_size || (mac_info.msg_head.status &&
+ mac_info.msg_head.status != SPNIC_PF_SET_VF_ALREADY)) {
+ PMD_DRV_LOG(ERR, "Delete MAC failed, err: %d, status: 0x%x, out size: 0x%x",
+ err, mac_info.msg_head.status, out_size);
+ return -EINVAL;
+ }
+
+ if (mac_info.msg_head.status == SPNIC_PF_SET_VF_ALREADY) {
+ PMD_DRV_LOG(WARNING, "PF has already set VF mac, Ignore delete operation");
+ return SPNIC_PF_SET_VF_ALREADY;
+ }
+
+ return 0;
+}
+
+int spnic_update_mac(void *hwdev, u8 *old_mac, u8 *new_mac, u16 vlan_id,
+ u16 func_id)
+{
+ struct spnic_port_mac_update mac_info;
+ u16 out_size = sizeof(mac_info);
+ int err;
+
+ if (!hwdev || !old_mac || !new_mac)
+ return -EINVAL;
+
+ if (vlan_id >= VLAN_N_VID) {
+ PMD_DRV_LOG(ERR, "Invalid VLAN number: %d", vlan_id);
+ return -EINVAL;
+ }
+
+ memset(&mac_info, 0, sizeof(mac_info));
+ mac_info.func_id = func_id;
+ mac_info.vlan_id = vlan_id;
+ memcpy(mac_info.old_mac, old_mac, ETH_ALEN);
+ memcpy(mac_info.new_mac, new_mac, ETH_ALEN);
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_CMD_UPDATE_MAC, &mac_info,
+ sizeof(mac_info), &mac_info, &out_size);
+ if (err || !out_size ||
+ spnic_check_mac_info(mac_info.msg_head.status, mac_info.vlan_id)) {
+ PMD_DRV_LOG(ERR, "Update MAC failed, err: %d, status: 0x%x, out size: 0x%x",
+ err, mac_info.msg_head.status, out_size);
+ return -EINVAL;
+ }
+
+ if (mac_info.msg_head.status == SPNIC_PF_SET_VF_ALREADY) {
+ PMD_DRV_LOG(WARNING, "PF has already set VF MAC. Ignore update operation");
+ return SPNIC_PF_SET_VF_ALREADY;
+ }
+
+ if (mac_info.msg_head.status == SPNIC_MGMT_STATUS_EXIST) {
+ PMD_DRV_LOG(INFO, "MAC is repeated. Ignore update operation");
+ return 0;
+ }
+
+ return 0;
+}
+
+int spnic_get_default_mac(void *hwdev, u8 *mac_addr, int ether_len)
+{
+ struct spnic_port_mac_set mac_info;
+ u16 out_size = sizeof(mac_info);
+ int err;
+
+ if (!hwdev || !mac_addr)
+ return -EINVAL;
+
+ memset(&mac_info, 0, sizeof(mac_info));
+ mac_info.func_id = spnic_global_func_id(hwdev);
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_CMD_GET_MAC,
+ &mac_info, sizeof(mac_info),
+ &mac_info, &out_size);
+ if (err || !out_size || mac_info.msg_head.status) {
+ PMD_DRV_LOG(ERR, "Get MAC failed, err: %d, status: 0x%x, out size: 0x%x",
+ err, mac_info.msg_head.status, out_size);
+ return -EINVAL;
+ }
+
+ memmove(mac_addr, mac_info.mac, ether_len);
+
+ return 0;
+}
+
+int spnic_get_port_info(void *hwdev, struct nic_port_info *port_info)
+{
+ struct spnic_cmd_port_info port_msg;
+ u16 out_size = sizeof(port_msg);
+ int err;
+
+ if (!hwdev || !port_info)
+ return -EINVAL;
+
+ memset(&port_msg, 0, sizeof(port_msg));
+ port_msg.port_id = spnic_physical_port_id(hwdev);
+
+ err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_PORT_INFO, &port_msg,
+ sizeof(port_msg), &port_msg, &out_size);
+ if (err || !out_size || port_msg.msg_head.status) {
+ PMD_DRV_LOG(ERR, "Get port info failed, err: %d, status: 0x%x, out size: 0x%x",
+ err, port_msg.msg_head.status, out_size);
+ return -EINVAL;
+ }
+
+ port_info->autoneg_cap = port_msg.autoneg_cap;
+ port_info->autoneg_state = port_msg.autoneg_state;
+ port_info->duplex = port_msg.duplex;
+ port_info->port_type = port_msg.port_type;
+ port_info->speed = port_msg.speed;
+ port_info->fec = port_msg.fec;
+
+ 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)
+{
+ u32 i, cmd_cnt = ARRAY_LEN(vf_mag_cmd_handler);
+
+ if (spnic_func_type(hwdev) == TYPE_VF) {
+ for (i = 0; i < cmd_cnt; i++) {
+ if (cmd == vf_mag_cmd_handler[i].cmd)
+ return spnic_mbox_to_pf(hwdev, SPNIC_MOD_HILINK,
+ cmd, buf_in, in_size,
+ buf_out, out_size, 0);
+ }
+ }
+
+ return spnic_msg_to_mgmt_sync(hwdev, SPNIC_MOD_HILINK, cmd, buf_in,
+ in_size, buf_out, out_size, 0);
+}
+
+static int mag_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ return _mag_msg_to_mgmt_sync(hwdev, cmd, buf_in, in_size, buf_out,
+ out_size);
+}
diff --git a/drivers/net/spnic/base/spnic_nic_cfg.h b/drivers/net/spnic/base/spnic_nic_cfg.h
new file mode 100644
index 0000000000..669e982876
--- /dev/null
+++ b/drivers/net/spnic/base/spnic_nic_cfg.h
@@ -0,0 +1,180 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
+ */
+
+#ifndef _SPNIC_NIC_CFG_H_
+#define _SPNIC_NIC_CFG_H_
+
+#ifndef ETH_ALEN
+#define ETH_ALEN 6
+#endif
+
+#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_PF_SET_VF_ALREADY 0x4
+#define SPNIC_MGMT_STATUS_EXIST 0x6
+#define CHECK_IPSU_15BIT 0x8000
+
+/* Structures for port info */
+struct nic_port_info {
+ u8 port_type;
+ u8 autoneg_cap;
+ u8 autoneg_state;
+ u8 duplex;
+ u8 speed;
+ u8 fec;
+};
+
+enum spnic_link_status {
+ SPNIC_LINK_DOWN = 0,
+ SPNIC_LINK_UP
+};
+
+enum nic_media_type {
+ MEDIA_UNKNOWN = -1,
+ MEDIA_FIBRE = 0,
+ MEDIA_COPPER,
+ MEDIA_BACKPLANE
+};
+
+enum nic_speed_level {
+ LINK_SPEED_10MB = 0,
+ LINK_SPEED_100MB,
+ LINK_SPEED_1GB,
+ LINK_SPEED_10GB,
+ LINK_SPEED_25GB,
+ LINK_SPEED_40GB,
+ LINK_SPEED_100GB,
+ LINK_SPEED_LEVELS,
+};
+
+struct spnic_port_mac_set {
+ struct mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 vlan_id;
+ u16 rsvd1;
+ u8 mac[ETH_ALEN];
+};
+
+struct spnic_port_mac_update {
+ struct mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 vlan_id;
+ u16 rsvd1;
+ u8 old_mac[ETH_ALEN];
+ u16 rsvd2;
+ u8 new_mac[ETH_ALEN];
+};
+
+struct spnic_cmd_port_info {
+ struct mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 rsvd1[3];
+ u8 port_type;
+ u8 autoneg_cap;
+ u8 autoneg_state;
+ u8 duplex;
+ u8 speed;
+ u8 fec;
+ u16 rsvd2;
+ u32 rsvd3[4];
+};
+
+struct spnic_cmd_link_state {
+ struct mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 state;
+ u16 rsvd1;
+};
+
+int l2nic_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size);
+
+/**
+ * Update MAC address to hardware
+ *
+ * @param[in] hwdev
+ * Device pointer to hwdev
+ * @param[in] old_mac
+ * Old MAC addr to delete
+ * @param[in] new_mac
+ * New MAC addr to update
+ * @param[in] vlan_id
+ * Vlan id
+ * @param func_id
+ * Function index
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_update_mac(void *hwdev, u8 *old_mac, u8 *new_mac, u16 vlan_id,
+ u16 func_id);
+
+/**
+ * Get the default mac address
+ *
+ * @param[in] hwdev
+ * Device pointer to hwdev
+ * @param[in] mac_addr
+ * Mac address from hardware
+ * @param[in] ether_len
+ * The length of mac address
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_get_default_mac(void *hwdev, u8 *mac_addr, int ether_len);
+
+/**
+ * Set mac address
+ *
+ * @param[in] hwdev
+ * Device pointer to hwdev
+ * @param[in] mac_addr
+ * Mac address from hardware
+ * @param[in] vlan_id
+ * Vlan id
+ * @param[in] func_id
+ * Function index
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_set_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id);
+
+/**
+ * Delete MAC address
+ *
+ * @param[in] hwdev
+ * Device pointer to hwdev
+ * @param[in] mac_addr
+ * MAC address from hardware
+ * @param[in] vlan_id
+ * Vlan id
+ * @param[in] func_id
+ * Function index
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_del_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id);
+
+/**
+ * Get port info
+ *
+ * @param[in] hwdev
+ * Device pointer to hwdev
+ * @param[out] port_info
+ * Port info, including autoneg, port type, duplex, speed and fec mode
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_get_port_info(void *hwdev, struct nic_port_info *port_info);
+
+#endif /* _SPNIC_NIC_CFG_H_ */
diff --git a/drivers/net/spnic/base/spnic_nic_event.c b/drivers/net/spnic/base/spnic_nic_event.c
index 07ea036d84..1c3621171a 100644
--- a/drivers/net/spnic/base/spnic_nic_event.c
+++ b/drivers/net/spnic/base/spnic_nic_event.c
@@ -9,16 +9,39 @@
#include "spnic_hwif.h"
#include "spnic_hwdev.h"
#include "spnic_mgmt.h"
+#include "spnic_nic_cfg.h"
#include "spnic_hwdev.h"
#include "spnic_nic_event.h"
-static void get_port_info(u8 link_state, struct rte_eth_link *link)
+void get_port_info(struct spnic_hwdev *hwdev, u8 link_state,
+ struct rte_eth_link *link)
{
+ uint32_t port_speed[LINK_SPEED_LEVELS] = {ETH_SPEED_NUM_10M,
+ ETH_SPEED_NUM_100M, ETH_SPEED_NUM_1G,
+ ETH_SPEED_NUM_10G, ETH_SPEED_NUM_25G,
+ ETH_SPEED_NUM_40G, ETH_SPEED_NUM_100G};
+ struct nic_port_info port_info = {0};
+ int err;
+
if (!link_state) {
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;
+ } else {
+ link->link_status = ETH_LINK_UP;
+
+ err = spnic_get_port_info(hwdev, &port_info);
+ if (err) {
+ link->link_speed = ETH_SPEED_NUM_NONE;
+ link->link_duplex = ETH_LINK_FULL_DUPLEX;
+ link->link_autoneg = ETH_LINK_FIXED;
+ } else {
+ link->link_speed = port_speed[port_info.speed %
+ LINK_SPEED_LEVELS];
+ link->link_duplex = port_info.duplex;
+ link->link_autoneg = port_info.autoneg_state;
+ }
}
}
@@ -51,7 +74,7 @@ static void link_status_event_handler(void *hwdev, void *buf_in,
spnic_link_event_stats(hwdev, link_status->state);
/* Link event reported only after set vport enable */
- get_port_info(link_status->state, &link);
+ get_port_info(dev, link_status->state, &link);
err = rte_eth_linkstatus_set((struct rte_eth_dev *)(dev->eth_dev),
&link);
if (!err)
diff --git a/drivers/net/spnic/base/spnic_nic_event.h b/drivers/net/spnic/base/spnic_nic_event.h
index eb41d76a7d..ac0c072887 100644
--- a/drivers/net/spnic/base/spnic_nic_event.h
+++ b/drivers/net/spnic/base/spnic_nic_event.h
@@ -5,13 +5,8 @@
#ifndef _SPNIC_NIC_EVENT_H_
#define _SPNIC_NIC_EVENT_H_
-struct spnic_cmd_link_state {
- struct mgmt_msg_head msg_head;
-
- u8 port_id;
- u8 state;
- u16 rsvd1;
-};
+void get_port_info(struct spnic_hwdev *hwdev, u8 link_state,
+ struct rte_eth_link *link);
void spnic_pf_event_handler(void *hwdev, __rte_unused void *pri_handle,
u16 cmd, void *buf_in, u16 in_size,
diff --git a/drivers/net/spnic/spnic_ethdev.c b/drivers/net/spnic/spnic_ethdev.c
index 228ed0c936..8f71280fa7 100644
--- a/drivers/net/spnic/spnic_ethdev.c
+++ b/drivers/net/spnic/spnic_ethdev.c
@@ -5,14 +5,23 @@
#include <rte_pci.h>
#include <rte_bus_pci.h>
#include <ethdev_pci.h>
+#include <rte_malloc.h>
#include <rte_errno.h>
#include <rte_ether.h>
#include "base/spnic_compat.h"
+#include "base/spnic_cmd.h"
#include "base/spnic_csr.h"
+#include "base/spnic_wq.h"
+#include "base/spnic_eqs.h"
+#include "base/spnic_mgmt.h"
+#include "base/spnic_cmdq.h"
#include "base/spnic_hwdev.h"
#include "base/spnic_hwif.h"
-
+#include "base/spnic_hw_cfg.h"
+#include "base/spnic_hw_comm.h"
+#include "base/spnic_nic_cfg.h"
+#include "base/spnic_nic_event.h"
#include "spnic_ethdev.h"
/* Driver-specific log messages type */
@@ -21,6 +30,58 @@ 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)
+{
+ 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));
+ }
+}
+
+/**
+ * Deinit mac_vlan table in hardware.
+ *
+ * @param[in] eth_dev
+ * Pointer to ethernet device structure.
+ */
+static void spnic_deinit_mac_addr(struct rte_eth_dev *eth_dev)
+{
+ struct spnic_nic_dev *nic_dev =
+ SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
+ u16 func_id = 0;
+ int err;
+ int i;
+
+ func_id = spnic_global_func_id(nic_dev->hwdev);
+
+ for (i = 0; i < SPNIC_MAX_UC_MAC_ADDRS; i++) {
+ if (rte_is_zero_ether_addr(ð_dev->data->mac_addrs[i]))
+ continue;
+
+ err = spnic_del_mac(nic_dev->hwdev,
+ eth_dev->data->mac_addrs[i].addr_bytes,
+ 0, func_id);
+ if (err && err != SPNIC_PF_SET_VF_ALREADY)
+ PMD_DRV_LOG(ERR, "Delete mac table failed, dev_name: %s",
+ eth_dev->data->name);
+
+ memset(ð_dev->data->mac_addrs[i], 0,
+ sizeof(struct rte_ether_addr));
+ }
+
+ /* Delete multicast mac addrs */
+ spnic_delete_mc_addr_list(nic_dev);
+}
+
/**
* Close the device.
*
@@ -38,13 +99,247 @@ static int spnic_dev_close(struct rte_eth_dev *eth_dev)
return 0;
}
+ spnic_deinit_mac_addr(eth_dev);
+ rte_free(nic_dev->mc_list);
+
+ rte_bit_relaxed_clear32(SPNIC_DEV_INTR_EN, &nic_dev->dev_status);
+
spnic_free_hwdev(nic_dev->hwdev);
+ eth_dev->dev_ops = NULL;
+
rte_free(nic_dev->hwdev);
nic_dev->hwdev = NULL;
return 0;
}
+/**
+ * Update MAC address
+ *
+ * @param[in] dev
+ * Pointer to ethernet device structure.
+ * @param[in] addr
+ * Pointer to MAC address
+ *
+ * @retval zero: Success
+ * @retval non-zero: Failure
+ */
+static int spnic_set_mac_addr(struct rte_eth_dev *dev,
+ struct rte_ether_addr *addr)
+{
+ struct spnic_nic_dev *nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+ char mac_addr[RTE_ETHER_ADDR_FMT_SIZE];
+ u16 func_id;
+ int err;
+
+ if (!rte_is_valid_assigned_ether_addr(addr)) {
+ rte_ether_format_addr(mac_addr, RTE_ETHER_ADDR_FMT_SIZE, addr);
+ PMD_DRV_LOG(ERR, "Set invalid MAC address %s", mac_addr);
+ return -EINVAL;
+ }
+
+ func_id = spnic_global_func_id(nic_dev->hwdev);
+ err = spnic_update_mac(nic_dev->hwdev,
+ nic_dev->default_addr.addr_bytes,
+ addr->addr_bytes, 0, func_id);
+ if (err)
+ return err;
+
+ rte_ether_addr_copy(addr, &nic_dev->default_addr);
+ rte_ether_format_addr(mac_addr, RTE_ETHER_ADDR_FMT_SIZE,
+ &nic_dev->default_addr);
+
+ PMD_DRV_LOG(INFO, "Set new MAC address %s", mac_addr);
+
+ return 0;
+}
+
+/**
+ * Remove a MAC address.
+ *
+ * @param[in] dev
+ * Pointer to ethernet device structure.
+ * @param[in] index
+ * MAC address index.
+ */
+static void spnic_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
+{
+ struct spnic_nic_dev *nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+ u16 func_id;
+ int err;
+
+ if (index >= SPNIC_MAX_UC_MAC_ADDRS) {
+ PMD_DRV_LOG(INFO, "Remove MAC index(%u) is out of range",
+ index);
+ return;
+ }
+
+ func_id = spnic_global_func_id(nic_dev->hwdev);
+ err = spnic_del_mac(nic_dev->hwdev,
+ dev->data->mac_addrs[index].addr_bytes,
+ 0, func_id);
+ if (err)
+ PMD_DRV_LOG(ERR, "Remove MAC index(%u) failed", index);
+}
+
+/**
+ * Add a MAC address.
+ *
+ * @param[in] dev
+ * Pointer to ethernet device structure.
+ * @param[in] mac_addr
+ * MAC address to register.
+ * @param[in] index
+ * MAC address index.
+ * @param[in] vmdq
+ * VMDq pool index to associate address with (unused_).
+ *
+ * @retval zero: Success
+ * @retval non-zero: Failure
+ */
+static int spnic_mac_addr_add(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mac_addr, uint32_t index,
+ __rte_unused uint32_t vmdq)
+{
+ struct spnic_nic_dev *nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+ unsigned int i;
+ u16 func_id;
+ int err;
+
+ if (!rte_is_valid_assigned_ether_addr(mac_addr)) {
+ PMD_DRV_LOG(ERR, "Add invalid MAC address");
+ return -EINVAL;
+ }
+
+ if (index >= SPNIC_MAX_UC_MAC_ADDRS) {
+ PMD_DRV_LOG(ERR, "Add MAC index(%u) is out of range", index);
+ return -EINVAL;
+ }
+
+ /* Make sure this address doesn't already be configured */
+ for (i = 0; i < SPNIC_MAX_UC_MAC_ADDRS; i++) {
+ if (rte_is_same_ether_addr(mac_addr,
+ &dev->data->mac_addrs[i])) {
+ PMD_DRV_LOG(ERR, "MAC address is already configured");
+ return -EADDRINUSE;
+ }
+ }
+
+ func_id = spnic_global_func_id(nic_dev->hwdev);
+ err = spnic_set_mac(nic_dev->hwdev, mac_addr->addr_bytes, 0, func_id);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+/**
+ * Set multicast MAC address
+ *
+ * @param[in] dev
+ * Pointer to ethernet device structure.
+ * @param[in] mc_addr_set
+ * Pointer to multicast MAC address
+ * @param[in] nb_mc_addr
+ * The number of multicast MAC address to set
+ *
+ * @retval zero: Success
+ * @retval non-zero: Failure
+ */
+static int spnic_set_mc_addr_list(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mc_addr_set,
+ uint32_t nb_mc_addr)
+{
+ struct spnic_nic_dev *nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+ char mac_addr[RTE_ETHER_ADDR_FMT_SIZE];
+ u16 func_id;
+ int err;
+ u32 i;
+
+ func_id = spnic_global_func_id(nic_dev->hwdev);
+
+ /* Delete old multi_cast addrs firstly */
+ spnic_delete_mc_addr_list(nic_dev);
+
+ if (nb_mc_addr > SPNIC_MAX_MC_MAC_ADDRS)
+ return -EINVAL;
+
+ for (i = 0; i < nb_mc_addr; i++) {
+ if (!rte_is_multicast_ether_addr(&mc_addr_set[i])) {
+ rte_ether_format_addr(mac_addr, RTE_ETHER_ADDR_FMT_SIZE,
+ &mc_addr_set[i]);
+ PMD_DRV_LOG(ERR, "Set mc MAC addr failed, addr(%s) invalid",
+ mac_addr);
+ return -EINVAL;
+ }
+ }
+
+ for (i = 0; i < nb_mc_addr; i++) {
+ err = spnic_set_mac(nic_dev->hwdev, mc_addr_set[i].addr_bytes,
+ 0, func_id);
+ if (err) {
+ spnic_delete_mc_addr_list(nic_dev);
+ return err;
+ }
+
+ rte_ether_addr_copy(&mc_addr_set[i], &nic_dev->mc_list[i]);
+ }
+
+ return 0;
+}
+static const struct eth_dev_ops spnic_pmd_ops = {
+ .mac_addr_set = spnic_set_mac_addr,
+ .mac_addr_remove = spnic_mac_addr_remove,
+ .mac_addr_add = spnic_mac_addr_add,
+ .set_mc_addr_list = spnic_set_mc_addr_list,
+};
+
+static const struct eth_dev_ops spnic_pmd_vf_ops = {
+ .mac_addr_set = spnic_set_mac_addr,
+ .mac_addr_remove = spnic_mac_addr_remove,
+ .mac_addr_add = spnic_mac_addr_add,
+ .set_mc_addr_list = spnic_set_mc_addr_list,
+};
+
+/**
+ * Init mac_vlan table in hardwares.
+ *
+ * @param[in] eth_dev
+ * Pointer to ethernet device structure.
+ *
+ * @retval zero: Success
+ * @retval non-zero: Failure
+ */
+static int spnic_init_mac_table(struct rte_eth_dev *eth_dev)
+{
+ struct spnic_nic_dev *nic_dev =
+ SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
+ u8 addr_bytes[RTE_ETHER_ADDR_LEN];
+ u16 func_id = 0;
+ int err = 0;
+
+ err = spnic_get_default_mac(nic_dev->hwdev, addr_bytes,
+ RTE_ETHER_ADDR_LEN);
+ if (err)
+ return err;
+
+ rte_ether_addr_copy((struct rte_ether_addr *)addr_bytes,
+ ð_dev->data->mac_addrs[0]);
+ if (rte_is_zero_ether_addr(ð_dev->data->mac_addrs[0]))
+ rte_eth_random_addr(eth_dev->data->mac_addrs[0].addr_bytes);
+
+ func_id = spnic_global_func_id(nic_dev->hwdev);
+ err = spnic_set_mac(nic_dev->hwdev,
+ eth_dev->data->mac_addrs[0].addr_bytes,
+ 0, func_id);
+ if (err && err != SPNIC_PF_SET_VF_ALREADY)
+ return err;
+
+ rte_ether_addr_copy(ð_dev->data->mac_addrs[0],
+ &nic_dev->default_addr);
+
+ return 0;
+}
static int spnic_func_init(struct rte_eth_dev *eth_dev)
{
@@ -63,11 +358,37 @@ static int spnic_func_init(struct rte_eth_dev *eth_dev)
}
nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
+ memset(nic_dev, 0, sizeof(*nic_dev));
snprintf(nic_dev->dev_name, sizeof(nic_dev->dev_name),
"spnic-%.4x:%.2x:%.2x.%x",
pci_dev->addr.domain, pci_dev->addr.bus,
pci_dev->addr.devid, pci_dev->addr.function);
+ /* Alloc mac_addrs */
+ eth_dev->data->mac_addrs = rte_zmalloc("spnic_mac",
+ SPNIC_MAX_UC_MAC_ADDRS * sizeof(struct rte_ether_addr), 0);
+ if (!eth_dev->data->mac_addrs) {
+ PMD_DRV_LOG(ERR, "Allocate %zx bytes to store MAC addresses "
+ "failed, dev_name: %s",
+ SPNIC_MAX_UC_MAC_ADDRS *
+ sizeof(struct rte_ether_addr),
+ eth_dev->data->name);
+ err = -ENOMEM;
+ goto alloc_eth_addr_fail;
+ }
+
+ nic_dev->mc_list = rte_zmalloc("spnic_mc",
+ SPNIC_MAX_MC_MAC_ADDRS * sizeof(struct rte_ether_addr), 0);
+ if (!nic_dev->mc_list) {
+ PMD_DRV_LOG(ERR, "Allocate %zx bytes to store multicast "
+ "addresses failed, dev_name: %s",
+ SPNIC_MAX_MC_MAC_ADDRS *
+ sizeof(struct rte_ether_addr),
+ eth_dev->data->name);
+ err = -ENOMEM;
+ goto alloc_mc_list_fail;
+ }
+
eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
/* Create hardware device */
nic_dev->hwdev = rte_zmalloc("spnic_hwdev", sizeof(*nic_dev->hwdev),
@@ -90,17 +411,42 @@ static int spnic_func_init(struct rte_eth_dev *eth_dev)
goto init_hwdev_fail;
}
+ 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_mac_table(eth_dev);
+ if (err) {
+ PMD_DRV_LOG(ERR, "Init mac table failed, dev_name: %s",
+ eth_dev->data->name);
+ goto init_mac_table_fail;
+ }
+
+ rte_bit_relaxed_set32(SPNIC_DEV_INTR_EN, &nic_dev->dev_status);
+
rte_bit_relaxed_set32(SPNIC_DEV_INIT, &nic_dev->dev_status);
PMD_DRV_LOG(INFO, "Initialize %s in primary succeed",
eth_dev->data->name);
return 0;
+init_mac_table_fail:
+ spnic_free_hwdev(nic_dev->hwdev);
+ eth_dev->dev_ops = NULL;
+
init_hwdev_fail:
rte_free(nic_dev->hwdev);
nic_dev->hwdev = NULL;
alloc_hwdev_mem_fail:
+ rte_free(nic_dev->mc_list);
+ nic_dev->mc_list = NULL;
+
+alloc_mc_list_fail:
+ rte_free(eth_dev->data->mac_addrs);
+ eth_dev->data->mac_addrs = NULL;
+
+alloc_eth_addr_fail:
PMD_DRV_LOG(ERR, "Initialize %s in primary failed",
eth_dev->data->name);
return err;
--
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 ` Yanling Song [this message]
2021-12-18 2:51 ` [PATCH v1 10/25] net/spnic: add function " Yanling Song
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=2bdd398a489d626cf86b62f169bfa366a50f0afa.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).