From patchwork Fri Sep 1 09:34:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Renyong Wan X-Patchwork-Id: 131060 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 61C394221E; Fri, 1 Sep 2023 11:37:48 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 20623402E1; Fri, 1 Sep 2023 11:36:05 +0200 (CEST) Received: from VLXDG1SPAM1.ramaxel.com (email.unionmem.com [221.4.138.186]) by mails.dpdk.org (Postfix) with ESMTP id 9922E402ED for ; Fri, 1 Sep 2023 11:36:00 +0200 (CEST) Received: from V12DG1MBS03.ramaxel.local ([172.26.18.33]) by VLXDG1SPAM1.ramaxel.com with ESMTP id 3819ZR7A069836; Fri, 1 Sep 2023 17:35:29 +0800 (GMT-8) (envelope-from wanry@3snic.com) Received: from localhost.localdomain (10.64.136.151) by V12DG1MBS03.ramaxel.local (172.26.18.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2375.17; Fri, 1 Sep 2023 17:35:28 +0800 From: To: CC: , Renyong Wan , Steven Song Subject: [PATCH v4 13/32] net/sssnic: support link status event Date: Fri, 1 Sep 2023 17:34:55 +0800 Message-ID: <20230901093514.224824-14-wanry@3snic.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230901093514.224824-1-wanry@3snic.com> References: <20230901093514.224824-1-wanry@3snic.com> MIME-Version: 1.0 X-Originating-IP: [10.64.136.151] X-ClientProxiedBy: V12DG1MBS03.ramaxel.local (172.26.18.33) To V12DG1MBS03.ramaxel.local (172.26.18.33) X-DNSRBL: X-SPAM-SOURCE-CHECK: pass X-MAIL: VLXDG1SPAM1.ramaxel.com 3819ZR7A069836 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Renyong Wan Signed-off-by: Steven Song Signed-off-by: Renyong Wan --- v2: * Fixed 'EINVAL' undeclared. --- doc/guides/nics/features/sssnic.ini | 1 + drivers/net/sssnic/base/meson.build | 1 + drivers/net/sssnic/base/sssnic_exception.c | 116 +++++++++++++++++++++ drivers/net/sssnic/base/sssnic_exception.h | 10 ++ drivers/net/sssnic/base/sssnic_hw.c | 46 ++++++++ drivers/net/sssnic/base/sssnic_hw.h | 22 ++++ drivers/net/sssnic/sssnic_ethdev.c | 6 +- drivers/net/sssnic/sssnic_ethdev_link.c | 98 +++++++++++++++++ drivers/net/sssnic/sssnic_ethdev_link.h | 2 + 9 files changed, 301 insertions(+), 1 deletion(-) create mode 100644 drivers/net/sssnic/base/sssnic_exception.c create mode 100644 drivers/net/sssnic/base/sssnic_exception.h diff --git a/doc/guides/nics/features/sssnic.ini b/doc/guides/nics/features/sssnic.ini index a0688e70ef..82b527ba26 100644 --- a/doc/guides/nics/features/sssnic.ini +++ b/doc/guides/nics/features/sssnic.ini @@ -5,6 +5,7 @@ ; [Features] Link status = Y +Link status event = Y Unicast MAC filter = Y Multicast MAC filter = Y Linux = Y diff --git a/drivers/net/sssnic/base/meson.build b/drivers/net/sssnic/base/meson.build index e93ca7b24b..cf0c177cab 100644 --- a/drivers/net/sssnic/base/meson.build +++ b/drivers/net/sssnic/base/meson.build @@ -9,6 +9,7 @@ sources = [ 'sssnic_workq.c', 'sssnic_ctrlq.c', 'sssnic_api.c', + 'sssnic_exception.c', ] c_args = cflags diff --git a/drivers/net/sssnic/base/sssnic_exception.c b/drivers/net/sssnic/base/sssnic_exception.c new file mode 100644 index 0000000000..738ca9c6cd --- /dev/null +++ b/drivers/net/sssnic/base/sssnic_exception.c @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2022 Shenzhen 3SNIC Information Technology Co., Ltd. + */ + +#include +#include +#include + +#include "../sssnic_log.h" +#include "sssnic_hw.h" +#include "sssnic_reg.h" +#include "sssnic_cmd.h" +#include "sssnic_msg.h" +#include "sssnic_eventq.h" +#include "sssnic_mbox.h" +#include "sssnic_exception.h" + +static void +sssnic_link_event_msg_handle(struct sssnic_hw *hw, struct sssnic_msg *msg, + __rte_unused enum sssnic_msg_chann_id chan_id) +{ + struct sssnic_netif_link_status_get_cmd *cmd; + sssnic_link_event_cb_t *cb; + enum sssnic_link_status status; + void *priv; + + cb = hw->link_event_handler.cb; + priv = hw->link_event_handler.priv; + + cmd = (struct sssnic_netif_link_status_get_cmd *)msg->data_buf; + if (cb != NULL) { + if (cmd->status) + status = SSSNIC_LINK_STATUS_UP; + else + status = SSSNIC_LINK_STATUS_DOWN; + + PMD_DRV_LOG(DEBUG, "Received sssnic%u link %s event", + SSSNIC_ETH_PORT_ID(hw), status ? "up" : "down"); + + return cb(cmd->port, status, priv); + } + + PMD_DRV_LOG(WARNING, "Link event was not processed, port=%u, status=%u", + cmd->port, cmd->status); +} + +static void +sssnic_netif_vf_link_status_msg_handle(struct sssnic_hw *hw, + struct sssnic_msg *msg) +{ + int ret; + + if (msg->ack != 0) { + msg->ack = 0; + msg->type = SSSNIC_MSG_TYPE_RESP; + msg->data_len = 1; /* indicate no data */ + ret = sssnic_mbox_send(hw, msg, NULL, 0, 0); + if (ret != 0) + PMD_DRV_LOG(ERR, + "Failed to send VF link status response, ret=%d", + ret); + } +} + +static void +sssnic_netif_exception_msg_handle(struct sssnic_hw *hw, struct sssnic_msg *msg, + enum sssnic_msg_chann_id chan_id) +{ + if (msg->command == SSSNIC_GET_NETIF_LINK_STATUS_CMD) { + if (SSSNIC_FUNC_TYPE(hw) == SSSNIC_FUNC_TYPE_VF) + sssnic_netif_vf_link_status_msg_handle(hw, msg); + + sssnic_link_event_msg_handle(hw, msg, chan_id); + return; + } + + PMD_DRV_LOG(WARNING, + "Netif exception message was not processed, cmd=%u", + msg->command); +} + +static int +sssnic_exception_msg_process(struct sssnic_msg *msg, + enum sssnic_msg_chann_id chan_id, void *priv) +{ + struct sssnic_hw *hw = (struct sssnic_hw *)priv; + + SSSNIC_DEBUG("command=%u, func=%u module=%u, type=%u, ack=%u, seq=%u, " + "status=%u, id=%u data_buf=%p, data_len=%u", + msg->command, msg->func, msg->module, msg->type, msg->ack, + msg->seg, msg->status, msg->id, msg->data_buf, msg->data_len); + + if (msg->module == SSSNIC_NETIF_MODULE) { + sssnic_netif_exception_msg_handle(hw, msg, chan_id); + return SSSNIC_MSG_DONE; + } + + PMD_DRV_LOG(WARNING, "Exception message was not processed, moule=%u", + msg->module); + + return SSSNIC_MSG_DONE; +} + +int +sssnic_exception_process_init(struct sssnic_hw *hw) +{ + if (hw == NULL) + return -EINVAL; + + sssnic_msg_rx_handler_register(hw, SSSNIC_MSG_CHAN_MPU, + SSSNIC_MSG_TYPE_REQ, sssnic_exception_msg_process, hw); + sssnic_msg_rx_handler_register(hw, SSSNIC_MSG_CHAN_MBOX, + SSSNIC_MSG_TYPE_REQ, sssnic_exception_msg_process, hw); + + return 0; +} diff --git a/drivers/net/sssnic/base/sssnic_exception.h b/drivers/net/sssnic/base/sssnic_exception.h new file mode 100644 index 0000000000..46f2f7465b --- /dev/null +++ b/drivers/net/sssnic/base/sssnic_exception.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2022 Shenzhen 3SNIC Information Technology Co., Ltd. + */ + +#ifndef _SSSNIC_EXCEPTION_H_ +#define _SSSNIC_EXCEPTION_H_ + +int sssnic_exception_process_init(struct sssnic_hw *hw); + +#endif /* _SSSNIC_EXCEPTION_H_ */ diff --git a/drivers/net/sssnic/base/sssnic_hw.c b/drivers/net/sssnic/base/sssnic_hw.c index 8f5f556bde..82eb4ea295 100644 --- a/drivers/net/sssnic/base/sssnic_hw.c +++ b/drivers/net/sssnic/base/sssnic_hw.c @@ -15,6 +15,7 @@ #include "sssnic_msg.h" #include "sssnic_mbox.h" #include "sssnic_ctrlq.h" +#include "sssnic_exception.h" static int wait_for_sssnic_hw_ready(struct sssnic_hw *hw) @@ -133,6 +134,17 @@ sssnic_msix_all_disable(struct sssnic_hw *hw) sssnic_msix_state_set(hw, i, SSSNIC_MSIX_DISABLE); } +void +sssnic_msix_resend_disable(struct sssnic_hw *hw, uint16_t msix_id) +{ + struct sssnic_msix_ctrl_reg reg; + + reg.u32 = 0; + reg.resend_timer_clr = SSSNIC_MSIX_DISABLE; + reg.msxi_idx = msix_id; + sssnic_cfg_reg_write(hw, SSSNIC_MSIX_CTRL_REG, reg.u32); +} + static void sssnic_pf_status_set(struct sssnic_hw *hw, enum sssnic_pf_status status) { @@ -276,6 +288,38 @@ sssnic_capability_init(struct sssnic_hw *hw) return 0; } +int +sssnic_link_event_callback_register(struct sssnic_hw *hw, + sssnic_link_event_cb_t *cb, void *priv) +{ + if (hw == NULL || cb == NULL) + return -EINVAL; + + hw->link_event_handler.cb = cb; + hw->link_event_handler.priv = priv; + + return 0; +} + +void +sssnic_link_event_callback_unregister(struct sssnic_hw *hw) +{ + if (hw != NULL) { + hw->link_event_handler.cb = NULL; + hw->link_event_handler.priv = NULL; + } +} + +void +sssnic_link_intr_handle(struct sssnic_hw *hw) +{ + PMD_DRV_LOG(DEBUG, "sssnic%u link interrupt triggered!", + SSSNIC_ETH_PORT_ID(hw)); + + sssnic_msix_resend_disable(hw, SSSNIC_LINK_INTR_MSIX_ID); + sssnic_eventq_flush(hw, SSSNIC_LINK_INTR_EVENTQ, 0); +} + static int sssnic_base_init(struct sssnic_hw *hw) { @@ -389,6 +433,8 @@ sssnic_hw_init(struct sssnic_hw *hw) goto capbility_init_fail; } + sssnic_exception_process_init(hw); + sssnic_pf_status_set(hw, SSSNIC_PF_STATUS_ACTIVE); return 0; diff --git a/drivers/net/sssnic/base/sssnic_hw.h b/drivers/net/sssnic/base/sssnic_hw.h index f8fe2ac7e1..e25f5595e6 100644 --- a/drivers/net/sssnic/base/sssnic_hw.h +++ b/drivers/net/sssnic/base/sssnic_hw.h @@ -44,6 +44,22 @@ struct sssnic_hw_attr { uint16_t num_irq; }; +enum sssnic_link_status { + SSSNIC_LINK_STATUS_DOWN, + SSSNIC_LINK_STATUS_UP, +}; + +#define SSSNIC_LINK_INTR_MSIX_ID 0 +#define SSSNIC_LINK_INTR_EVENTQ 0 + +typedef void sssnic_link_event_cb_t(uint8_t port, + enum sssnic_link_status status, void *priv); + +struct sssnic_link_event_handler { + sssnic_link_event_cb_t *cb; + void *priv; +}; + struct sssnic_hw { struct rte_pci_device *pci_dev; uint8_t *cfg_base_addr; @@ -55,6 +71,7 @@ struct sssnic_hw { struct sssnic_msg_inbox *msg_inbox; struct sssnic_mbox *mbox; struct sssnic_ctrlq *ctrlq; + struct sssnic_link_event_handler link_event_handler; uint8_t num_eventqs; uint8_t phy_port; uint16_t eth_port_id; @@ -82,5 +99,10 @@ enum sssnic_module { int sssnic_hw_init(struct sssnic_hw *hw); void sssnic_hw_shutdown(struct sssnic_hw *hw); void sssnic_msix_state_set(struct sssnic_hw *hw, uint16_t msix_id, int state); +void sssnic_msix_resend_disable(struct sssnic_hw *hw, uint16_t msix_id); +int sssnic_link_event_callback_register(struct sssnic_hw *hw, + sssnic_link_event_cb_t *cb, void *priv); +void sssnic_link_event_callback_unregister(struct sssnic_hw *hw); +void sssnic_link_intr_handle(struct sssnic_hw *hw); #endif /* _SSSNIC_HW_H_ */ diff --git a/drivers/net/sssnic/sssnic_ethdev.c b/drivers/net/sssnic/sssnic_ethdev.c index 4e546cca66..1e2b5c0450 100644 --- a/drivers/net/sssnic/sssnic_ethdev.c +++ b/drivers/net/sssnic/sssnic_ethdev.c @@ -334,6 +334,7 @@ sssnic_ethdev_release(struct rte_eth_dev *ethdev) { struct sssnic_hw *hw = SSSNIC_ETHDEV_TO_HW(ethdev); + sssnic_ethdev_link_intr_disable(ethdev); sssnic_ethdev_mac_addrs_clean(ethdev); sssnic_hw_shutdown(hw); rte_free(hw); @@ -391,6 +392,9 @@ sssnic_ethdev_init(struct rte_eth_dev *ethdev) ethdev->dev_ops = &sssnic_ethdev_ops; + sssnic_ethdev_link_update(ethdev, 0); + sssnic_ethdev_link_intr_enable(ethdev); + return 0; mac_addrs_init_fail: @@ -440,7 +444,7 @@ static const struct rte_pci_id sssnic_pci_id_map[] = { static struct rte_pci_driver sssnic_pmd = { .id_table = sssnic_pci_id_map, - .drv_flags = RTE_PCI_DRV_NEED_MAPPING, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, .probe = sssnic_pci_probe, .remove = sssnic_pci_remove, }; diff --git a/drivers/net/sssnic/sssnic_ethdev_link.c b/drivers/net/sssnic/sssnic_ethdev_link.c index 04e2d2e5d2..9e932c51dd 100644 --- a/drivers/net/sssnic/sssnic_ethdev_link.c +++ b/drivers/net/sssnic/sssnic_ethdev_link.c @@ -109,3 +109,101 @@ sssnic_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete) out: return rte_eth_linkstatus_set(ethdev, &link); } + +static void +sssnic_ethdev_link_status_print(struct rte_eth_dev *ethdev, + struct rte_eth_link *link) +{ + if (link->link_status) { + PMD_DRV_LOG(INFO, "Port %u Link Up - speed %s - %s", + ethdev->data->port_id, + rte_eth_link_speed_to_str(link->link_speed), + link->link_duplex == RTE_ETH_LINK_FULL_DUPLEX ? + "full-duplex" : + "half-duplex"); + } else { + PMD_DRV_LOG(INFO, "Port %u Link Down", ethdev->data->port_id); + } +} + +static void +sssnic_ethdev_link_event_cb(__rte_unused uint8_t port, + __rte_unused enum sssnic_link_status status, void *arg) +{ + struct rte_eth_dev *ethdev = (struct rte_eth_dev *)arg; + struct rte_eth_link link; + int ret; + + memset(&link, 0, sizeof(link)); + sssnic_ethdev_link_get(ethdev, &link); + + ret = rte_eth_linkstatus_set(ethdev, &link); + if (ret == 0) { + sssnic_ethdev_link_status_print(ethdev, &link); + rte_eth_dev_callback_process(ethdev, RTE_ETH_EVENT_INTR_LSC, + NULL); + } +} + +static void +sssnic_ethdev_link_intr_callback(void *arg) +{ + struct rte_eth_dev *ethdev = (struct rte_eth_dev *)arg; + struct sssnic_hw *hw; + + hw = SSSNIC_ETHDEV_TO_HW(ethdev); + + sssnic_link_intr_handle(hw); +} + +void +sssnic_ethdev_link_intr_enable(struct rte_eth_dev *ethdev) +{ + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(ethdev); + struct sssnic_hw *hw = SSSNIC_ETHDEV_TO_HW(ethdev); + int ret; + + sssnic_link_event_callback_register(hw, sssnic_ethdev_link_event_cb, + ethdev); + + ret = rte_intr_callback_register(pci_dev->intr_handle, + sssnic_ethdev_link_intr_callback, ethdev); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to register port %u intr callback!", + ethdev->data->port_id); + + sssnic_link_event_callback_unregister(hw); + + return; + } + + ret = rte_intr_enable(pci_dev->intr_handle); + if (ret != 0) { + PMD_DRV_LOG(ERR, "Failed to enable port %u interrupt!", + ethdev->data->port_id); + + rte_intr_callback_unregister(pci_dev->intr_handle, + sssnic_ethdev_link_intr_callback, ethdev); + sssnic_link_event_callback_unregister(hw); + + return; + } + + sssnic_msix_state_set(hw, SSSNIC_LINK_INTR_MSIX_ID, SSSNIC_MSIX_ENABLE); +} + +void +sssnic_ethdev_link_intr_disable(struct rte_eth_dev *ethdev) +{ + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(ethdev); + struct sssnic_hw *hw = SSSNIC_ETHDEV_TO_HW(ethdev); + + sssnic_msix_state_set(hw, SSSNIC_LINK_INTR_MSIX_ID, + SSSNIC_MSIX_DISABLE); + + rte_intr_disable(pci_dev->intr_handle); + rte_intr_callback_unregister(pci_dev->intr_handle, + sssnic_ethdev_link_intr_callback, ethdev); + + sssnic_link_event_callback_unregister(hw); +} diff --git a/drivers/net/sssnic/sssnic_ethdev_link.h b/drivers/net/sssnic/sssnic_ethdev_link.h index 00ad13fe9b..52a86b4771 100644 --- a/drivers/net/sssnic/sssnic_ethdev_link.h +++ b/drivers/net/sssnic/sssnic_ethdev_link.h @@ -8,5 +8,7 @@ int sssnic_ethdev_set_link_up(struct rte_eth_dev *ethdev); int sssnic_ethdev_set_link_down(struct rte_eth_dev *ethdev); int sssnic_ethdev_link_update(struct rte_eth_dev *ethdev, int wait_to_complete); +void sssnic_ethdev_link_intr_enable(struct rte_eth_dev *ethdev); +void sssnic_ethdev_link_intr_disable(struct rte_eth_dev *ethdev); #endif /* _SSSNIC_ETHDEV_LINK_H_ */