From: Yanling Song songyl@ramaxel.com
Ramaxel inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4ZR0O CVE: NA
----------------------------------
There are some issues of the driver that cannot be fixed now. The driver is not good enough for the LTS quality requirements of openEuler,so remove it.
Signed-off-by: Yanling Song songyl@ramaxel.com Reviewed-by: Yang Gan yanggan@ramaxel.com Acked-by: Xie Xiuqi xiexiuqi@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- arch/arm64/configs/openeuler_defconfig | 2 - arch/x86/configs/openeuler_defconfig | 2 - drivers/net/ethernet/Kconfig | 1 - drivers/net/ethernet/Makefile | 1 - drivers/net/ethernet/ramaxel/Kconfig | 20 - drivers/net/ethernet/ramaxel/Makefile | 6 - drivers/net/ethernet/ramaxel/spnic/Kconfig | 14 - drivers/net/ethernet/ramaxel/spnic/Makefile | 39 - .../ethernet/ramaxel/spnic/hw/sphw_api_cmd.c | 1165 ----------- .../ethernet/ramaxel/spnic/hw/sphw_api_cmd.h | 277 --- .../ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h | 127 -- .../net/ethernet/ramaxel/spnic/hw/sphw_cmdq.c | 1573 --------------- .../net/ethernet/ramaxel/spnic/hw/sphw_cmdq.h | 195 -- .../ethernet/ramaxel/spnic/hw/sphw_comm_cmd.h | 60 - .../ramaxel/spnic/hw/sphw_comm_msg_intf.h | 273 --- .../ethernet/ramaxel/spnic/hw/sphw_common.c | 88 - .../ethernet/ramaxel/spnic/hw/sphw_common.h | 106 - .../net/ethernet/ramaxel/spnic/hw/sphw_crm.h | 982 --------- .../net/ethernet/ramaxel/spnic/hw/sphw_csr.h | 158 -- .../net/ethernet/ramaxel/spnic/hw/sphw_eqs.c | 1272 ------------ .../net/ethernet/ramaxel/spnic/hw/sphw_eqs.h | 157 -- .../net/ethernet/ramaxel/spnic/hw/sphw_hw.h | 643 ------ .../ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c | 1341 ------------ .../ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h | 329 --- .../ethernet/ramaxel/spnic/hw/sphw_hw_comm.c | 1280 ------------ .../ethernet/ramaxel/spnic/hw/sphw_hw_comm.h | 45 - .../ethernet/ramaxel/spnic/hw/sphw_hwdev.c | 1324 ------------ .../ethernet/ramaxel/spnic/hw/sphw_hwdev.h | 93 - .../net/ethernet/ramaxel/spnic/hw/sphw_hwif.c | 886 -------- .../net/ethernet/ramaxel/spnic/hw/sphw_hwif.h | 102 - .../net/ethernet/ramaxel/spnic/hw/sphw_mbox.c | 1792 ----------------- .../net/ethernet/ramaxel/spnic/hw/sphw_mbox.h | 271 --- .../net/ethernet/ramaxel/spnic/hw/sphw_mgmt.c | 895 -------- .../net/ethernet/ramaxel/spnic/hw/sphw_mgmt.h | 106 - .../ramaxel/spnic/hw/sphw_mgmt_msg_base.h | 19 - .../net/ethernet/ramaxel/spnic/hw/sphw_mt.h | 533 ----- .../ramaxel/spnic/hw/sphw_prof_adap.c | 94 - .../ramaxel/spnic/hw/sphw_prof_adap.h | 49 - .../ethernet/ramaxel/spnic/hw/sphw_profile.h | 36 - .../net/ethernet/ramaxel/spnic/hw/sphw_wq.c | 152 -- .../net/ethernet/ramaxel/spnic/hw/sphw_wq.h | 119 -- .../net/ethernet/ramaxel/spnic/spnic_dbg.c | 752 ------- .../net/ethernet/ramaxel/spnic/spnic_dcb.c | 965 --------- .../net/ethernet/ramaxel/spnic/spnic_dcb.h | 56 - .../ethernet/ramaxel/spnic/spnic_dev_mgmt.c | 811 -------- .../ethernet/ramaxel/spnic/spnic_dev_mgmt.h | 78 - .../ethernet/ramaxel/spnic/spnic_ethtool.c | 994 --------- .../ramaxel/spnic/spnic_ethtool_stats.c | 1035 ---------- .../net/ethernet/ramaxel/spnic/spnic_filter.c | 411 ---- .../net/ethernet/ramaxel/spnic/spnic_irq.c | 178 -- .../net/ethernet/ramaxel/spnic/spnic_lld.c | 937 --------- .../net/ethernet/ramaxel/spnic/spnic_lld.h | 75 - .../ethernet/ramaxel/spnic/spnic_mag_cfg.c | 778 ------- .../ethernet/ramaxel/spnic/spnic_mag_cmd.h | 643 ------ .../net/ethernet/ramaxel/spnic/spnic_main.c | 924 --------- .../ramaxel/spnic/spnic_mgmt_interface.h | 605 ------ .../ethernet/ramaxel/spnic/spnic_netdev_ops.c | 1526 -------------- .../net/ethernet/ramaxel/spnic/spnic_nic.h | 148 -- .../ethernet/ramaxel/spnic/spnic_nic_cfg.c | 1334 ------------ .../ethernet/ramaxel/spnic/spnic_nic_cfg.h | 709 ------- .../ethernet/ramaxel/spnic/spnic_nic_cfg_vf.c | 658 ------ .../ethernet/ramaxel/spnic/spnic_nic_cmd.h | 105 - .../ethernet/ramaxel/spnic/spnic_nic_dbg.c | 151 -- .../ethernet/ramaxel/spnic/spnic_nic_dbg.h | 16 - .../ethernet/ramaxel/spnic/spnic_nic_dev.h | 354 ---- .../ethernet/ramaxel/spnic/spnic_nic_event.c | 506 ----- .../net/ethernet/ramaxel/spnic/spnic_nic_io.c | 1123 ----------- .../net/ethernet/ramaxel/spnic/spnic_nic_io.h | 305 --- .../net/ethernet/ramaxel/spnic/spnic_nic_qp.h | 416 ---- .../net/ethernet/ramaxel/spnic/spnic_ntuple.c | 841 -------- .../ethernet/ramaxel/spnic/spnic_pci_id_tbl.h | 12 - .../net/ethernet/ramaxel/spnic/spnic_rss.c | 741 ------- .../net/ethernet/ramaxel/spnic/spnic_rss.h | 50 - .../ethernet/ramaxel/spnic/spnic_rss_cfg.c | 333 --- drivers/net/ethernet/ramaxel/spnic/spnic_rx.c | 1238 ------------ drivers/net/ethernet/ramaxel/spnic/spnic_rx.h | 118 -- .../net/ethernet/ramaxel/spnic/spnic_sriov.c | 200 -- .../net/ethernet/ramaxel/spnic/spnic_sriov.h | 24 - drivers/net/ethernet/ramaxel/spnic/spnic_tx.c | 877 -------- drivers/net/ethernet/ramaxel/spnic/spnic_tx.h | 129 -- 80 files changed, 37783 deletions(-) delete mode 100644 drivers/net/ethernet/ramaxel/Kconfig delete mode 100644 drivers/net/ethernet/ramaxel/Makefile delete mode 100644 drivers/net/ethernet/ramaxel/spnic/Kconfig delete mode 100644 drivers/net/ethernet/ramaxel/spnic/Makefile delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_cmdq.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_cmdq.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_comm_cmd.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_comm_msg_intf.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_common.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_common.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_crm.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_csr.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_eqs.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_eqs.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwdev.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwdev.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwif.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwif.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_mbox.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_mbox.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt_msg_base.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_mt.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_profile.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_wq.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/hw/sphw_wq.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_dbg.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_dcb.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_dcb.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_dev_mgmt.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_dev_mgmt.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_ethtool.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_ethtool_stats.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_filter.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_irq.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_lld.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_lld.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_mag_cfg.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_mag_cmd.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_main.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_mgmt_interface.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_netdev_ops.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg_vf.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_cmd.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_dbg.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_dbg.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_dev.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_event.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_io.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_io.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_nic_qp.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_ntuple.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_pci_id_tbl.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_rss.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_rss.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_rss_cfg.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_rx.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_rx.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_sriov.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_sriov.h delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_tx.c delete mode 100644 drivers/net/ethernet/ramaxel/spnic/spnic_tx.h
diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index 1fd250cc103c..5020f94eea34 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -2815,8 +2815,6 @@ CONFIG_NET_VENDOR_QUALCOMM=y # CONFIG_QCA7000_SPI is not set CONFIG_QCOM_EMAC=m # CONFIG_RMNET is not set -CONFIG_NET_VENDOR_RAMAXEL=y -CONFIG_SPNIC=m # CONFIG_NET_VENDOR_RDC is not set CONFIG_NET_VENDOR_REALTEK=y CONFIG_8139CP=m diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index cd9aaba18fa4..351a89b54d7f 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -2792,8 +2792,6 @@ CONFIG_QED_ISCSI=y CONFIG_QED_FCOE=y CONFIG_QED_OOO=y # CONFIG_NET_VENDOR_QUALCOMM is not set -CONFIG_NET_VENDOR_RAMAXEL=y -CONFIG_SPNIC=m # CONFIG_NET_VENDOR_RDC is not set CONFIG_NET_VENDOR_REALTEK=y # CONFIG_ATP is not set diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index 7d7f6a972c28..6998a8cb3faa 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -160,7 +160,6 @@ source "drivers/net/ethernet/pasemi/Kconfig" source "drivers/net/ethernet/pensando/Kconfig" source "drivers/net/ethernet/qlogic/Kconfig" source "drivers/net/ethernet/qualcomm/Kconfig" -source "drivers/net/ethernet/ramaxel/Kconfig" source "drivers/net/ethernet/rdc/Kconfig" source "drivers/net/ethernet/realtek/Kconfig" source "drivers/net/ethernet/renesas/Kconfig" diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index 5e375d5a6230..6a7d68ea63ed 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -71,7 +71,6 @@ obj-$(CONFIG_NET_VENDOR_PACKET_ENGINES) += packetengines/ obj-$(CONFIG_NET_VENDOR_PASEMI) += pasemi/ obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/ obj-$(CONFIG_NET_VENDOR_QUALCOMM) += qualcomm/ -obj-$(CONFIG_NET_VENDOR_RAMAXEL) += ramaxel/ obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/ obj-$(CONFIG_NET_VENDOR_RENESAS) += renesas/ obj-$(CONFIG_NET_VENDOR_RDC) += rdc/ diff --git a/drivers/net/ethernet/ramaxel/Kconfig b/drivers/net/ethernet/ramaxel/Kconfig deleted file mode 100644 index 987c7eb4880b..000000000000 --- a/drivers/net/ethernet/ramaxel/Kconfig +++ /dev/null @@ -1,20 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Ramaxel driver configuration -# - -config NET_VENDOR_RAMAXEL - bool "Ramaxel devices" - default y - help - If you have a network (Ethernet) card belonging to this class, say Y. - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about Ramaxel cards. If you say Y, you will be asked - for your specific card in the following questions. - -if NET_VENDOR_RAMAXEL - - source "drivers/net/ethernet/ramaxel/spnic/Kconfig" - -endif # NET_VENDOR_RAMAXEL diff --git a/drivers/net/ethernet/ramaxel/Makefile b/drivers/net/ethernet/ramaxel/Makefile deleted file mode 100644 index 087f570c2257..000000000000 --- a/drivers/net/ethernet/ramaxel/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Makefile for the Ramaxel device drivers. -# - -obj-$(CONFIG_SPNIC) += spnic/ \ No newline at end of file diff --git a/drivers/net/ethernet/ramaxel/spnic/Kconfig b/drivers/net/ethernet/ramaxel/spnic/Kconfig deleted file mode 100644 index d0cb81041e8c..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Ramaxel SPNIC driver configuration -# - -config SPNIC - tristate "Ramaxel PCIE Network Interface Card" - default n - depends on PCI_MSI && NUMA && PCI_IOV && (X86 || ARM64) - help - This driver supports Ramaxel PCIE Ethernet cards. - To compile this driver as part of the kernel, choose Y here. - If unsure, choose N. - The default is N. diff --git a/drivers/net/ethernet/ramaxel/spnic/Makefile b/drivers/net/ethernet/ramaxel/spnic/Makefile deleted file mode 100644 index 207e1d9c431a..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_SPNIC) += spnic.o - -subdir-ccflags-y += -I$(srctree)/$(src)/hw - -spnic-objs := hw/sphw_common.o \ - hw/sphw_hwif.o \ - hw/sphw_eqs.o \ - hw/sphw_mbox.o \ - hw/sphw_api_cmd.o \ - hw/sphw_mgmt.o \ - hw/sphw_wq.o \ - hw/sphw_cmdq.o \ - hw/sphw_prof_adap.o \ - hw/sphw_hw_cfg.o \ - hw/sphw_hw_comm.o \ - hw/sphw_hwdev.o \ - spnic_sriov.o \ - spnic_lld.o \ - spnic_dev_mgmt.o \ - spnic_main.o \ - spnic_tx.o \ - spnic_rx.o \ - spnic_rss.o \ - spnic_ntuple.o \ - spnic_dcb.o \ - spnic_ethtool.o \ - spnic_ethtool_stats.o \ - spnic_dbg.o \ - spnic_irq.o \ - spnic_filter.o \ - spnic_netdev_ops.o \ - spnic_nic_cfg.o \ - spnic_mag_cfg.o \ - spnic_nic_cfg_vf.o \ - spnic_rss_cfg.o \ - spnic_nic_event.o \ - spnic_nic_io.o \ - spnic_nic_dbg.o diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.c deleted file mode 100644 index b459ca322515..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.c +++ /dev/null @@ -1,1165 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/completion.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <linux/semaphore.h> -#include <linux/jiffies.h> -#include <linux/delay.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_common.h" -#include "sphw_hwdev.h" -#include "sphw_csr.h" -#include "sphw_hwif.h" -#include "sphw_api_cmd.h" - -#define API_CMD_CHAIN_CELL_SIZE_SHIFT 6U - -#define API_CMD_CELL_DESC_SIZE 8 -#define API_CMD_CELL_DATA_ADDR_SIZE 8 - -#define API_CHAIN_NUM_CELLS 32 -#define API_CHAIN_CELL_SIZE 128 -#define API_CHAIN_RSP_DATA_SIZE 128 - -#define API_CMD_CELL_WB_ADDR_SIZE 8 - -#define API_CHAIN_CELL_ALIGNMENT 8 - -#define API_CMD_TIMEOUT 10000 -#define API_CMD_STATUS_TIMEOUT 100000 - -#define API_CMD_BUF_SIZE 2048ULL - -#define API_CMD_NODE_ALIGN_SIZE 512ULL -#define API_PAYLOAD_ALIGN_SIZE 64ULL - -#define API_CHAIN_RESP_ALIGNMENT 128ULL - -#define COMPLETION_TIMEOUT_DEFAULT 1000UL -#define POLLING_COMPLETION_TIMEOUT_DEFAULT 1000U - -#define API_CMD_RESPONSE_DATA_PADDR(val) be64_to_cpu(*((u64 *)(val))) - -#define READ_API_CMD_PRIV_DATA(id, token) ((((u32)(id)) << 16) + (token)) -#define WRITE_API_CMD_PRIV_DATA(id) (((u8)(id)) << 16) - -#define MASKED_IDX(chain, idx) ((idx) & ((chain)->num_cells - 1)) - -#define SIZE_4BYTES(size) (ALIGN((u32)(size), 4U) >> 2) -#define SIZE_8BYTES(size) (ALIGN((u32)(size), 8U) >> 3) - -enum api_cmd_data_format { - SGL_DATA = 1, -}; - -enum api_cmd_type { - API_CMD_WRITE_TYPE = 0, - API_CMD_READ_TYPE = 1, -}; - -enum api_cmd_bypass { - NOT_BYPASS = 0, - BYPASS = 1, -}; - -enum api_cmd_resp_aeq { - NOT_TRIGGER = 0, - TRIGGER = 1, -}; - -enum api_cmd_chn_code { - APICHN_0 = 0, -}; - -enum api_cmd_chn_rsvd { - APICHN_VALID = 0, - APICHN_INVALID = 1, -}; - -#define API_DESC_LEN 7 - -static u8 xor_chksum_set(void *data) -{ - int idx; - u8 checksum = 0; - u8 *val = data; - - for (idx = 0; idx < API_DESC_LEN; idx++) - checksum ^= val[idx]; - - return checksum; -} - -static void set_prod_idx(struct sphw_api_cmd_chain *chain) -{ - enum sphw_api_cmd_chain_type chain_type = chain->chain_type; - struct sphw_hwif *hwif = chain->hwdev->hwif; - u32 hw_prod_idx_addr = SPHW_CSR_API_CMD_CHAIN_PI_ADDR(chain_type); - u32 prod_idx = chain->prod_idx; - - sphw_hwif_write_reg(hwif, hw_prod_idx_addr, prod_idx); -} - -static u32 get_hw_cons_idx(struct sphw_api_cmd_chain *chain) -{ - u32 addr, val; - - addr = SPHW_CSR_API_CMD_STATUS_0_ADDR(chain->chain_type); - val = sphw_hwif_read_reg(chain->hwdev->hwif, addr); - - return SPHW_API_CMD_STATUS_GET(val, CONS_IDX); -} - -static void dump_api_chain_reg(struct sphw_api_cmd_chain *chain) -{ - void *dev = chain->hwdev->dev_hdl; - u32 addr, val; - - addr = SPHW_CSR_API_CMD_STATUS_0_ADDR(chain->chain_type); - val = sphw_hwif_read_reg(chain->hwdev->hwif, addr); - - sdk_err(dev, "Chain type: 0x%x, cpld error: 0x%x, check error: 0x%x, current fsm: 0x%x\n", - chain->chain_type, SPHW_API_CMD_STATUS_GET(val, CPLD_ERR), - SPHW_API_CMD_STATUS_GET(val, CHKSUM_ERR), - SPHW_API_CMD_STATUS_GET(val, FSM)); - - sdk_err(dev, "Chain hw current ci: 0x%x\n", - SPHW_API_CMD_STATUS_GET(val, CONS_IDX)); - - addr = SPHW_CSR_API_CMD_CHAIN_PI_ADDR(chain->chain_type); - val = sphw_hwif_read_reg(chain->hwdev->hwif, addr); - sdk_err(dev, "Chain hw current pi: 0x%x\n", val); -} - -/** - * chain_busy - check if the chain is still processing last requests - * @chain: chain to check - **/ -static int chain_busy(struct sphw_api_cmd_chain *chain) -{ - void *dev = chain->hwdev->dev_hdl; - struct sphw_api_cmd_cell_ctxt *ctxt; - u64 resp_header; - - ctxt = &chain->cell_ctxt[chain->prod_idx]; - - switch (chain->chain_type) { - case SPHW_API_CMD_MULTI_READ: - case SPHW_API_CMD_POLL_READ: - resp_header = be64_to_cpu(ctxt->resp->header); - if (ctxt->status && - !SPHW_API_CMD_RESP_HEADER_VALID(resp_header)) { - sdk_err(dev, "Context(0x%x) busy!, pi: %u, resp_header: 0x%08x%08x\n", - ctxt->status, chain->prod_idx, - upper_32_bits(resp_header), - lower_32_bits(resp_header)); - dump_api_chain_reg(chain); - return -EBUSY; - } - break; - case SPHW_API_CMD_POLL_WRITE: - case SPHW_API_CMD_WRITE_TO_MGMT_CPU: - case SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU: - chain->cons_idx = get_hw_cons_idx(chain); - - if (chain->cons_idx == MASKED_IDX(chain, chain->prod_idx + 1)) { - sdk_err(dev, "API CMD chain %d is busy, cons_idx = %u, prod_idx = %u\n", - chain->chain_type, chain->cons_idx, - chain->prod_idx); - dump_api_chain_reg(chain); - return -EBUSY; - } - break; - default: - sdk_err(dev, "Unknown Chain type %d\n", chain->chain_type); - return -EINVAL; - } - - return 0; -} - -/** - * get_cell_data_size - get the data size of specific cell type - * @type: chain type - **/ -static u16 get_cell_data_size(enum sphw_api_cmd_chain_type type) -{ - u16 cell_data_size = 0; - - switch (type) { - case SPHW_API_CMD_POLL_READ: - cell_data_size = ALIGN(API_CMD_CELL_DESC_SIZE + - API_CMD_CELL_WB_ADDR_SIZE + - API_CMD_CELL_DATA_ADDR_SIZE, - API_CHAIN_CELL_ALIGNMENT); - break; - - case SPHW_API_CMD_WRITE_TO_MGMT_CPU: - case SPHW_API_CMD_POLL_WRITE: - case SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU: - cell_data_size = ALIGN(API_CMD_CELL_DESC_SIZE + - API_CMD_CELL_DATA_ADDR_SIZE, - API_CHAIN_CELL_ALIGNMENT); - break; - default: - break; - } - - return cell_data_size; -} - -/** - * prepare_cell_ctrl - prepare the ctrl of the cell for the command - * @cell_ctrl: the control of the cell to set the control into it - * @cell_len: the size of the cell - **/ -static void prepare_cell_ctrl(u64 *cell_ctrl, u16 cell_len) -{ - u64 ctrl; - u8 chksum; - - ctrl = SPHW_API_CMD_CELL_CTRL_SET(SIZE_8BYTES(cell_len), CELL_LEN) | - SPHW_API_CMD_CELL_CTRL_SET(0ULL, RD_DMA_ATTR_OFF) | - SPHW_API_CMD_CELL_CTRL_SET(0ULL, WR_DMA_ATTR_OFF); - - chksum = xor_chksum_set(&ctrl); - - ctrl |= SPHW_API_CMD_CELL_CTRL_SET(chksum, XOR_CHKSUM); - - /* The data in the HW should be in Big Endian Format */ - *cell_ctrl = cpu_to_be64(ctrl); -} - -/** - * prepare_api_cmd - prepare API CMD command - * @chain: chain for the command - * @cell: the cell of the command - * @node_id: destination node on the card that will receive the command - * @cmd: command data - * @cmd_size: the command size - **/ -static void prepare_api_cmd(struct sphw_api_cmd_chain *chain, - struct sphw_api_cmd_cell *cell, u8 node_id, - const void *cmd, u16 cmd_size) -{ - struct sphw_api_cmd_cell_ctxt *cell_ctxt; - u32 priv; - - cell_ctxt = &chain->cell_ctxt[chain->prod_idx]; - - switch (chain->chain_type) { - case SPHW_API_CMD_POLL_READ: - priv = READ_API_CMD_PRIV_DATA(chain->chain_type, - cell_ctxt->saved_prod_idx); - cell->desc = SPHW_API_CMD_DESC_SET(SGL_DATA, API_TYPE) | - SPHW_API_CMD_DESC_SET(API_CMD_READ_TYPE, RD_WR) | - SPHW_API_CMD_DESC_SET(BYPASS, MGMT_BYPASS) | - SPHW_API_CMD_DESC_SET(NOT_TRIGGER, RESP_AEQE_EN) | - SPHW_API_CMD_DESC_SET(priv, PRIV_DATA); - break; - case SPHW_API_CMD_POLL_WRITE: - priv = WRITE_API_CMD_PRIV_DATA(chain->chain_type); - cell->desc = SPHW_API_CMD_DESC_SET(SGL_DATA, API_TYPE) | - SPHW_API_CMD_DESC_SET(API_CMD_WRITE_TYPE, RD_WR) | - SPHW_API_CMD_DESC_SET(BYPASS, MGMT_BYPASS) | - SPHW_API_CMD_DESC_SET(NOT_TRIGGER, RESP_AEQE_EN) | - SPHW_API_CMD_DESC_SET(priv, PRIV_DATA); - break; - case SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU: - case SPHW_API_CMD_WRITE_TO_MGMT_CPU: - priv = WRITE_API_CMD_PRIV_DATA(chain->chain_type); - cell->desc = SPHW_API_CMD_DESC_SET(SGL_DATA, API_TYPE) | - SPHW_API_CMD_DESC_SET(API_CMD_WRITE_TYPE, RD_WR) | - SPHW_API_CMD_DESC_SET(NOT_BYPASS, MGMT_BYPASS) | - SPHW_API_CMD_DESC_SET(TRIGGER, RESP_AEQE_EN) | - SPHW_API_CMD_DESC_SET(priv, PRIV_DATA); - break; - default: - sdk_err(chain->hwdev->dev_hdl, "Unknown Chain type: %d\n", - chain->chain_type); - return; - } - - cell->desc |= SPHW_API_CMD_DESC_SET(APICHN_0, APICHN_CODE) | - SPHW_API_CMD_DESC_SET(APICHN_VALID, APICHN_RSVD); - - cell->desc |= SPHW_API_CMD_DESC_SET(node_id, DEST) | - SPHW_API_CMD_DESC_SET(SIZE_4BYTES(cmd_size), SIZE); - - cell->desc |= SPHW_API_CMD_DESC_SET(xor_chksum_set(&cell->desc), - XOR_CHKSUM); - - /* The data in the HW should be in Big Endian Format */ - cell->desc = cpu_to_be64(cell->desc); - - memcpy(cell_ctxt->api_cmd_vaddr, cmd, cmd_size); -} - -/** - * prepare_cell - prepare cell ctrl and cmd in the current producer cell - * @chain: chain for the command - * @node_id: destination node on the card that will receive the command - * @cmd: command data - * @cmd_size: the command size - * Return: 0 - success, negative - failure - **/ -static void prepare_cell(struct sphw_api_cmd_chain *chain, u8 node_id, - const void *cmd, u16 cmd_size) -{ - struct sphw_api_cmd_cell *curr_node; - u16 cell_size; - - curr_node = chain->curr_node; - - cell_size = get_cell_data_size(chain->chain_type); - - prepare_cell_ctrl(&curr_node->ctrl, cell_size); - prepare_api_cmd(chain, curr_node, node_id, cmd, cmd_size); -} - -static inline void cmd_chain_prod_idx_inc(struct sphw_api_cmd_chain *chain) -{ - chain->prod_idx = MASKED_IDX(chain, chain->prod_idx + 1); -} - -static void issue_api_cmd(struct sphw_api_cmd_chain *chain) -{ - set_prod_idx(chain); -} - -/** - * api_cmd_status_update - update the status of the chain - * @chain: chain to update - **/ -static void api_cmd_status_update(struct sphw_api_cmd_chain *chain) -{ - struct sphw_api_cmd_status *wb_status; - enum sphw_api_cmd_chain_type chain_type; - u64 status_header; - u32 buf_desc; - - wb_status = chain->wb_status; - - buf_desc = be32_to_cpu(wb_status->buf_desc); - if (SPHW_API_CMD_STATUS_GET(buf_desc, CHKSUM_ERR)) - return; - - status_header = be64_to_cpu(wb_status->header); - chain_type = SPHW_API_CMD_STATUS_HEADER_GET(status_header, CHAIN_ID); - if (chain_type >= SPHW_API_CMD_MAX) - return; - - if (chain_type != chain->chain_type) - return; - - chain->cons_idx = SPHW_API_CMD_STATUS_GET(buf_desc, CONS_IDX); -} - -static enum sphw_wait_return wait_for_status_poll_handler(void *priv_data) -{ - struct sphw_api_cmd_chain *chain = priv_data; - - if (!chain->hwdev->chip_present_flag) - return WAIT_PROCESS_ERR; - - api_cmd_status_update(chain); - /* SYNC API CMD cmd should start after prev cmd finished */ - if (chain->cons_idx == chain->prod_idx) - return WAIT_PROCESS_CPL; - - return WAIT_PROCESS_WAITING; -} - -/** - * wait_for_status_poll - wait for write to mgmt command to complete - * @chain: the chain of the command - * Return: 0 - success, negative - failure - **/ -static int wait_for_status_poll(struct sphw_api_cmd_chain *chain) -{ - return sphw_wait_for_timeout(chain, wait_for_status_poll_handler, - API_CMD_STATUS_TIMEOUT, 100); -} - -static void copy_resp_data(struct sphw_api_cmd_cell_ctxt *ctxt, void *ack, - u16 ack_size) -{ - struct sphw_api_cmd_resp_fmt *resp = ctxt->resp; - - memcpy(ack, &resp->resp_data, ack_size); - ctxt->status = 0; -} - -static enum sphw_wait_return check_cmd_resp_handler(void *priv_data) -{ - struct sphw_api_cmd_cell_ctxt *ctxt = priv_data; - u64 resp_header; - u8 resp_status; - - resp_header = be64_to_cpu(ctxt->resp->header); - rmb(); /* read the latest header */ - - if (SPHW_API_CMD_RESP_HEADER_VALID(resp_header)) { - resp_status = SPHW_API_CMD_RESP_HEAD_GET(resp_header, STATUS); - if (resp_status) { - pr_err("Api chain response data err, status: %u\n", - resp_status); - return WAIT_PROCESS_ERR; - } - - return WAIT_PROCESS_CPL; - } - - return WAIT_PROCESS_WAITING; -} - -/** - * prepare_cell - polling for respense data of the read api-command - * @chain: pointer to api cmd chain - * - * Return: 0 - success, negative - failure - **/ -static int wait_for_resp_polling(struct sphw_api_cmd_cell_ctxt *ctxt) -{ - return sphw_wait_for_timeout(ctxt, check_cmd_resp_handler, - POLLING_COMPLETION_TIMEOUT_DEFAULT, - USEC_PER_MSEC); -} - -/** - * wait_for_api_cmd_completion - wait for command to complete - * @chain: chain for the command - * Return: 0 - success, negative - failure - **/ -static int wait_for_api_cmd_completion(struct sphw_api_cmd_chain *chain, - struct sphw_api_cmd_cell_ctxt *ctxt, - void *ack, u16 ack_size) -{ - void *dev = chain->hwdev->dev_hdl; - int err = 0; - - switch (chain->chain_type) { - case SPHW_API_CMD_POLL_READ: - err = wait_for_resp_polling(ctxt); - if (!err) - copy_resp_data(ctxt, ack, ack_size); - else - sdk_err(dev, "API CMD poll response timeout\n"); - break; - case SPHW_API_CMD_POLL_WRITE: - case SPHW_API_CMD_WRITE_TO_MGMT_CPU: - err = wait_for_status_poll(chain); - if (err) { - sdk_err(dev, "API CMD Poll status timeout, chain type: %d\n", - chain->chain_type); - break; - } - break; - case SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU: - /* No need to wait */ - break; - default: - sdk_err(dev, "Unknown API CMD Chain type: %d\n", - chain->chain_type); - err = -EINVAL; - break; - } - - if (err) - dump_api_chain_reg(chain); - - return err; -} - -static inline void update_api_cmd_ctxt(struct sphw_api_cmd_chain *chain, - struct sphw_api_cmd_cell_ctxt *ctxt) -{ - ctxt->status = 1; - ctxt->saved_prod_idx = chain->prod_idx; - if (ctxt->resp) { - ctxt->resp->header = 0; - - /* make sure "header" was cleared */ - wmb(); - } -} - -/** - * api_cmd - API CMD command - * @chain: chain for the command - * @node_id: destination node on the card that will receive the command - * @cmd: command data - * @size: the command size - * Return: 0 - success, negative - failure - **/ -static int api_cmd(struct sphw_api_cmd_chain *chain, u8 node_id, - const void *cmd, u16 cmd_size, void *ack, u16 ack_size) -{ - struct sphw_api_cmd_cell_ctxt *ctxt = NULL; - - if (chain->chain_type == SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU) - spin_lock(&chain->async_lock); - else - down(&chain->sem); - ctxt = &chain->cell_ctxt[chain->prod_idx]; - if (chain_busy(chain)) { - if (chain->chain_type == SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU) - spin_unlock(&chain->async_lock); - else - up(&chain->sem); - return -EBUSY; - } - update_api_cmd_ctxt(chain, ctxt); - - prepare_cell(chain, node_id, cmd, cmd_size); - - cmd_chain_prod_idx_inc(chain); - - wmb(); /* issue the command */ - - issue_api_cmd(chain); - - /* incremented prod idx, update ctxt */ - - chain->curr_node = chain->cell_ctxt[chain->prod_idx].cell_vaddr; - if (chain->chain_type == SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU) - spin_unlock(&chain->async_lock); - else - up(&chain->sem); - - return wait_for_api_cmd_completion(chain, ctxt, ack, ack_size); -} - -/** - * sphw_api_cmd_write - Write API CMD command - * @chain: chain for write command - * @node_id: destination node on the card that will receive the command - * @cmd: command data - * @size: the command size - * Return: 0 - success, negative - failure - **/ -int sphw_api_cmd_write(struct sphw_api_cmd_chain *chain, u8 node_id, const void *cmd, u16 size) -{ - /* Verify the chain type */ - return api_cmd(chain, node_id, cmd, size, NULL, 0); -} - -/** - * sphw_api_cmd_read - Read API CMD command - * @chain: chain for read command - * @node_id: destination node on the card that will receive the command - * @cmd: command data - * @size: the command size - * Return: 0 - success, negative - failure - **/ -int sphw_api_cmd_read(struct sphw_api_cmd_chain *chain, u8 node_id, const void *cmd, u16 size, - void *ack, u16 ack_size) -{ - return api_cmd(chain, node_id, cmd, size, ack, ack_size); -} - -static enum sphw_wait_return check_chain_restart_handler(void *priv_data) -{ - struct sphw_api_cmd_chain *cmd_chain = priv_data; - u32 reg_addr, val; - - reg_addr = SPHW_CSR_API_CMD_CHAIN_REQ_ADDR(cmd_chain->chain_type); - val = sphw_hwif_read_reg(cmd_chain->hwdev->hwif, reg_addr); - if (!SPHW_API_CMD_CHAIN_REQ_GET(val, RESTART)) - return WAIT_PROCESS_CPL; - - return WAIT_PROCESS_WAITING; -} - -/** - * api_cmd_hw_restart - restart the chain in the HW - * @chain: the API CMD specific chain to restart - **/ -static int api_cmd_hw_restart(struct sphw_api_cmd_chain *cmd_chain) -{ - struct sphw_hwif *hwif = cmd_chain->hwdev->hwif; - u32 reg_addr, val; - - /* Read Modify Write */ - reg_addr = SPHW_CSR_API_CMD_CHAIN_REQ_ADDR(cmd_chain->chain_type); - val = sphw_hwif_read_reg(hwif, reg_addr); - - val = SPHW_API_CMD_CHAIN_REQ_CLEAR(val, RESTART); - val |= SPHW_API_CMD_CHAIN_REQ_SET(1, RESTART); - - sphw_hwif_write_reg(hwif, reg_addr, val); - - return sphw_wait_for_timeout(cmd_chain, check_chain_restart_handler, - API_CMD_TIMEOUT, USEC_PER_MSEC); -} - -/** - * api_cmd_ctrl_init - set the control register of a chain - * @chain: the API CMD specific chain to set control register for - **/ -static void api_cmd_ctrl_init(struct sphw_api_cmd_chain *chain) -{ - struct sphw_hwif *hwif = chain->hwdev->hwif; - u32 reg_addr, ctrl; - u32 size; - - /* Read Modify Write */ - reg_addr = SPHW_CSR_API_CMD_CHAIN_CTRL_ADDR(chain->chain_type); - - size = (u32)ilog2(chain->cell_size >> API_CMD_CHAIN_CELL_SIZE_SHIFT); - - ctrl = sphw_hwif_read_reg(hwif, reg_addr); - - ctrl = SPHW_API_CMD_CHAIN_CTRL_CLEAR(ctrl, AEQE_EN) & - SPHW_API_CMD_CHAIN_CTRL_CLEAR(ctrl, CELL_SIZE); - - ctrl |= SPHW_API_CMD_CHAIN_CTRL_SET(0, AEQE_EN) | - SPHW_API_CMD_CHAIN_CTRL_SET(size, CELL_SIZE); - - sphw_hwif_write_reg(hwif, reg_addr, ctrl); -} - -/** - * api_cmd_set_status_addr - set the status address of a chain in the HW - * @chain: the API CMD specific chain to set status address for - **/ -static void api_cmd_set_status_addr(struct sphw_api_cmd_chain *chain) -{ - struct sphw_hwif *hwif = chain->hwdev->hwif; - u32 addr, val; - - addr = SPHW_CSR_API_CMD_STATUS_HI_ADDR(chain->chain_type); - val = upper_32_bits(chain->wb_status_paddr); - sphw_hwif_write_reg(hwif, addr, val); - - addr = SPHW_CSR_API_CMD_STATUS_LO_ADDR(chain->chain_type); - val = lower_32_bits(chain->wb_status_paddr); - sphw_hwif_write_reg(hwif, addr, val); -} - -/** - * api_cmd_set_num_cells - set the number cells of a chain in the HW - * @chain: the API CMD specific chain to set the number of cells for - **/ -static void api_cmd_set_num_cells(struct sphw_api_cmd_chain *chain) -{ - struct sphw_hwif *hwif = chain->hwdev->hwif; - u32 addr, val; - - addr = SPHW_CSR_API_CMD_CHAIN_NUM_CELLS_ADDR(chain->chain_type); - val = chain->num_cells; - sphw_hwif_write_reg(hwif, addr, val); -} - -/** - * api_cmd_head_init - set the head cell of a chain in the HW - * @chain: the API CMD specific chain to set the head for - **/ -static void api_cmd_head_init(struct sphw_api_cmd_chain *chain) -{ - struct sphw_hwif *hwif = chain->hwdev->hwif; - u32 addr, val; - - addr = SPHW_CSR_API_CMD_CHAIN_HEAD_HI_ADDR(chain->chain_type); - val = upper_32_bits(chain->head_cell_paddr); - sphw_hwif_write_reg(hwif, addr, val); - - addr = SPHW_CSR_API_CMD_CHAIN_HEAD_LO_ADDR(chain->chain_type); - val = lower_32_bits(chain->head_cell_paddr); - sphw_hwif_write_reg(hwif, addr, val); -} - -static enum sphw_wait_return check_chain_ready_handler(void *priv_data) -{ - struct sphw_api_cmd_chain *chain = priv_data; - u32 addr, val; - u32 hw_cons_idx; - - addr = SPHW_CSR_API_CMD_STATUS_0_ADDR(chain->chain_type); - val = sphw_hwif_read_reg(chain->hwdev->hwif, addr); - hw_cons_idx = SPHW_API_CMD_STATUS_GET(val, CONS_IDX); - - /* wait for HW cons idx to be updated */ - if (hw_cons_idx == chain->cons_idx) - return WAIT_PROCESS_CPL; - return WAIT_PROCESS_WAITING; -} - -/** - * wait_for_ready_chain - wait for the chain to be ready - * @chain: the API CMD specific chain to wait for - * Return: 0 - success, negative - failure - **/ -static int wait_for_ready_chain(struct sphw_api_cmd_chain *chain) -{ - return sphw_wait_for_timeout(chain, check_chain_ready_handler, - API_CMD_TIMEOUT, USEC_PER_MSEC); -} - -/** - * api_cmd_chain_hw_clean - clean the HW - * @chain: the API CMD specific chain - **/ -static void api_cmd_chain_hw_clean(struct sphw_api_cmd_chain *chain) -{ - struct sphw_hwif *hwif = chain->hwdev->hwif; - u32 addr, ctrl; - - addr = SPHW_CSR_API_CMD_CHAIN_CTRL_ADDR(chain->chain_type); - - ctrl = sphw_hwif_read_reg(hwif, addr); - ctrl = SPHW_API_CMD_CHAIN_CTRL_CLEAR(ctrl, RESTART_EN) & - SPHW_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_ERR) & - SPHW_API_CMD_CHAIN_CTRL_CLEAR(ctrl, AEQE_EN) & - SPHW_API_CMD_CHAIN_CTRL_CLEAR(ctrl, XOR_CHK_EN) & - SPHW_API_CMD_CHAIN_CTRL_CLEAR(ctrl, CELL_SIZE); - - sphw_hwif_write_reg(hwif, addr, ctrl); -} - -/** - * api_cmd_chain_hw_init - initialize the chain in the HW - * @chain: the API CMD specific chain to initialize in HW - * Return: 0 - success, negative - failure - **/ -static int api_cmd_chain_hw_init(struct sphw_api_cmd_chain *chain) -{ - api_cmd_chain_hw_clean(chain); - - api_cmd_set_status_addr(chain); - - if (api_cmd_hw_restart(chain)) { - sdk_err(chain->hwdev->dev_hdl, "Failed to restart api_cmd_hw\n"); - return -EBUSY; - } - - api_cmd_ctrl_init(chain); - api_cmd_set_num_cells(chain); - api_cmd_head_init(chain); - - return wait_for_ready_chain(chain); -} - -/** - * alloc_cmd_buf - allocate a dma buffer for API CMD command - * @chain: the API CMD specific chain for the cmd - * @cell: the cell in the HW for the cmd - * @cell_idx: the index of the cell - * Return: 0 - success, negative - failure - **/ -static int alloc_cmd_buf(struct sphw_api_cmd_chain *chain, - struct sphw_api_cmd_cell *cell, u32 cell_idx) -{ - struct sphw_api_cmd_cell_ctxt *cell_ctxt; - void *dev = chain->hwdev->dev_hdl; - void *buf_vaddr; - u64 buf_paddr; - int err = 0; - - buf_vaddr = (u8 *)((u64)chain->buf_vaddr_base + - chain->buf_size_align * cell_idx); - buf_paddr = chain->buf_paddr_base + - chain->buf_size_align * cell_idx; - - cell_ctxt = &chain->cell_ctxt[cell_idx]; - - cell_ctxt->api_cmd_vaddr = buf_vaddr; - - /* set the cmd DMA address in the cell */ - switch (chain->chain_type) { - case SPHW_API_CMD_POLL_READ: - cell->read.hw_cmd_paddr = cpu_to_be64(buf_paddr); - break; - case SPHW_API_CMD_WRITE_TO_MGMT_CPU: - case SPHW_API_CMD_POLL_WRITE: - case SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU: - /* The data in the HW should be in Big Endian Format */ - cell->write.hw_cmd_paddr = cpu_to_be64(buf_paddr); - break; - default: - sdk_err(dev, "Unknown API CMD Chain type: %d\n", - chain->chain_type); - err = -EINVAL; - break; - } - - return err; -} - -/** - * alloc_cmd_buf - allocate a resp buffer for API CMD command - * @chain: the API CMD specific chain for the cmd - * @cell: the cell in the HW for the cmd - * @cell_idx: the index of the cell - **/ -static void alloc_resp_buf(struct sphw_api_cmd_chain *chain, - struct sphw_api_cmd_cell *cell, u32 cell_idx) -{ - struct sphw_api_cmd_cell_ctxt *cell_ctxt; - void *resp_vaddr; - u64 resp_paddr; - - resp_vaddr = (u8 *)((u64)chain->rsp_vaddr_base + - chain->rsp_size_align * cell_idx); - resp_paddr = chain->rsp_paddr_base + - chain->rsp_size_align * cell_idx; - - cell_ctxt = &chain->cell_ctxt[cell_idx]; - - cell_ctxt->resp = resp_vaddr; - cell->read.hw_wb_resp_paddr = cpu_to_be64(resp_paddr); -} - -static int sphw_alloc_api_cmd_cell_buf(struct sphw_api_cmd_chain *chain, u32 cell_idx, - struct sphw_api_cmd_cell *node) -{ - void *dev = chain->hwdev->dev_hdl; - int err; - - /* For read chain, we should allocate buffer for the response data */ - if (chain->chain_type == SPHW_API_CMD_MULTI_READ || - chain->chain_type == SPHW_API_CMD_POLL_READ) - alloc_resp_buf(chain, node, cell_idx); - - switch (chain->chain_type) { - case SPHW_API_CMD_WRITE_TO_MGMT_CPU: - case SPHW_API_CMD_POLL_WRITE: - case SPHW_API_CMD_POLL_READ: - case SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU: - err = alloc_cmd_buf(chain, node, cell_idx); - if (err) { - sdk_err(dev, "Failed to allocate cmd buffer\n"); - goto alloc_cmd_buf_err; - } - break; - /* For api command write and api command read, the data section - * is directly inserted in the cell, so no need to allocate. - */ - case SPHW_API_CMD_MULTI_READ: - chain->cell_ctxt[cell_idx].api_cmd_vaddr = - &node->read.hw_cmd_paddr; /* to do: who int this*/ - break; - default: - sdk_err(dev, "Unsupported API CMD chain type\n"); - err = -EINVAL; - goto alloc_cmd_buf_err; - } - - return 0; - -alloc_cmd_buf_err: - - return err; -} - -/** - * api_cmd_create_cell - create API CMD cell of specific chain - * @chain: the API CMD specific chain to create its cell - * @cell_idx: the cell index to create - * @pre_node: previous cell - * @node_vaddr: the virt addr of the cell - * Return: 0 - success, negative - failure - **/ -static int api_cmd_create_cell(struct sphw_api_cmd_chain *chain, u32 cell_idx, - struct sphw_api_cmd_cell *pre_node, - struct sphw_api_cmd_cell **node_vaddr) -{ - struct sphw_api_cmd_cell_ctxt *cell_ctxt; - struct sphw_api_cmd_cell *node; - void *cell_vaddr; - u64 cell_paddr; - int err; - - cell_vaddr = (void *)((u64)chain->cell_vaddr_base + - chain->cell_size_align * cell_idx); - cell_paddr = chain->cell_paddr_base + - chain->cell_size_align * cell_idx; - - cell_ctxt = &chain->cell_ctxt[cell_idx]; - cell_ctxt->cell_vaddr = cell_vaddr; - node = cell_ctxt->cell_vaddr; - - if (!pre_node) { - chain->head_node = cell_vaddr; - chain->head_cell_paddr = cell_paddr; - } else { - /* The data in the HW should be in Big Endian Format */ - pre_node->next_cell_paddr = cpu_to_be64(cell_paddr); - } - - /* Driver software should make sure that there is an empty API - * command cell at the end the chain - */ - node->next_cell_paddr = 0; - - err = sphw_alloc_api_cmd_cell_buf(chain, cell_idx, node); - if (err) - return err; - - *node_vaddr = node; - - return 0; -} - -/** - * api_cmd_create_cells - create API CMD cells for specific chain - * @chain: the API CMD specific chain - * Return: 0 - success, negative - failure - **/ -static int api_cmd_create_cells(struct sphw_api_cmd_chain *chain) -{ - struct sphw_api_cmd_cell *node = NULL, *pre_node = NULL; - void *dev = chain->hwdev->dev_hdl; - u32 cell_idx; - int err; - - for (cell_idx = 0; cell_idx < chain->num_cells; cell_idx++) { - err = api_cmd_create_cell(chain, cell_idx, pre_node, &node); - if (err) { - sdk_err(dev, "Failed to create API CMD cell\n"); - return err; - } - - pre_node = node; - } - - if (!node) - return -EFAULT; - - /* set the Final node to point on the start */ - node->next_cell_paddr = cpu_to_be64(chain->head_cell_paddr); - - /* set the current node to be the head */ - chain->curr_node = chain->head_node; - return 0; -} - -/** - * api_chain_init - initialize API CMD specific chain - * @chain: the API CMD specific chain to initialize - * @attr: attributes to set in the chain - * Return: 0 - success, negative - failure - **/ -static int api_chain_init(struct sphw_api_cmd_chain *chain, - struct sphw_api_cmd_chain_attr *attr) -{ - void *dev = chain->hwdev->dev_hdl; - size_t cell_ctxt_size; - size_t cells_buf_size; - int err; - - chain->chain_type = attr->chain_type; - chain->num_cells = attr->num_cells; - chain->cell_size = attr->cell_size; - chain->rsp_size = attr->rsp_size; - - chain->prod_idx = 0; - chain->cons_idx = 0; - - if (chain->chain_type == SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU) - spin_lock_init(&chain->async_lock); - else - sema_init(&chain->sem, 1); - - cell_ctxt_size = chain->num_cells * sizeof(*chain->cell_ctxt); - if (!cell_ctxt_size) { - sdk_err(dev, "Api chain cell size cannot be zero\n"); - return -EINVAL; - } - - chain->cell_ctxt = kzalloc(cell_ctxt_size, GFP_KERNEL); - if (!chain->cell_ctxt) { - sdk_err(dev, "Failed to allocate cell contexts for a chain\n"); - return -ENOMEM; - } - - chain->wb_status = dma_alloc_coherent(dev, sizeof(*chain->wb_status), - &chain->wb_status_paddr, GFP_KERNEL); - if (!chain->wb_status) { - sdk_err(dev, "Failed to allocate DMA wb status\n"); - err = -ENOMEM; - goto alloc_wb_status_err; - } - - chain->cell_size_align = ALIGN((u64)chain->cell_size, - API_CMD_NODE_ALIGN_SIZE); - chain->rsp_size_align = ALIGN((u64)chain->rsp_size, - API_CHAIN_RESP_ALIGNMENT); - chain->buf_size_align = ALIGN(API_CMD_BUF_SIZE, API_PAYLOAD_ALIGN_SIZE); - - cells_buf_size = (chain->cell_size_align + chain->rsp_size_align + - chain->buf_size_align) * chain->num_cells; - - err = sphw_dma_alloc_coherent_align(dev, cells_buf_size, API_CMD_NODE_ALIGN_SIZE, - GFP_KERNEL, &chain->cells_addr); - if (err) { - sdk_err(dev, "Failed to allocate API CMD cells buffer\n"); - goto alloc_cells_buf_err; - } - - chain->cell_vaddr_base = chain->cells_addr.align_vaddr; - chain->cell_paddr_base = chain->cells_addr.align_paddr; - - chain->rsp_vaddr_base = (u8 *)((u64)chain->cell_vaddr_base + - chain->cell_size_align * chain->num_cells); - chain->rsp_paddr_base = chain->cell_paddr_base + - chain->cell_size_align * chain->num_cells; - - chain->buf_vaddr_base = (u8 *)((u64)chain->rsp_vaddr_base + - chain->rsp_size_align * chain->num_cells); - chain->buf_paddr_base = chain->rsp_paddr_base + - chain->rsp_size_align * chain->num_cells; - - return 0; - -alloc_cells_buf_err: - dma_free_coherent(dev, sizeof(*chain->wb_status), - chain->wb_status, chain->wb_status_paddr); - -alloc_wb_status_err: - kfree(chain->cell_ctxt); - - return err; -} - -/** - * api_chain_free - free API CMD specific chain - * @chain: the API CMD specific chain to free - **/ -static void api_chain_free(struct sphw_api_cmd_chain *chain) -{ - void *dev = chain->hwdev->dev_hdl; - - sphw_dma_free_coherent_align(dev, &chain->cells_addr); - - dma_free_coherent(dev, sizeof(*chain->wb_status), - chain->wb_status, chain->wb_status_paddr); - kfree(chain->cell_ctxt); -} - -/** - * api_cmd_create_chain - create API CMD specific chain - * @chain: the API CMD specific chain to create - * @attr: attributes to set in the chain - * Return: 0 - success, negative - failure - **/ -static int api_cmd_create_chain(struct sphw_api_cmd_chain **cmd_chain, - struct sphw_api_cmd_chain_attr *attr) -{ - struct sphw_hwdev *hwdev = attr->hwdev; - struct sphw_api_cmd_chain *chain = NULL; - int err; - - if (attr->num_cells & (attr->num_cells - 1)) { - sdk_err(hwdev->dev_hdl, "Invalid number of cells, must be power of 2\n"); - return -EINVAL; - } - - chain = kzalloc(sizeof(*chain), GFP_KERNEL); - if (!chain) - return -ENOMEM; - - chain->hwdev = hwdev; - - err = api_chain_init(chain, attr); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to initialize chain\n"); - goto chain_init_err; - } - - err = api_cmd_create_cells(chain); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to create cells for API CMD chain\n"); - goto create_cells_err; - } - - err = api_cmd_chain_hw_init(chain); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to initialize chain HW\n"); - goto chain_hw_init_err; - } - - *cmd_chain = chain; - return 0; - -chain_hw_init_err: -create_cells_err: - api_chain_free(chain); - -chain_init_err: - kfree(chain); - return err; -} - -/** - * api_cmd_destroy_chain - destroy API CMD specific chain - * @chain: the API CMD specific chain to destroy - **/ -static void api_cmd_destroy_chain(struct sphw_api_cmd_chain *chain) -{ - api_chain_free(chain); - kfree(chain); -} - -/** - * sphw_api_cmd_init - Initialize all the API CMD chains - * @hwif: the hardware interface of a pci function device - * @chain: the API CMD chains that will be initialized - * Return: 0 - success, negative - failure - **/ -int sphw_api_cmd_init(struct sphw_hwdev *hwdev, struct sphw_api_cmd_chain **chain) -{ - void *dev = hwdev->dev_hdl; - struct sphw_api_cmd_chain_attr attr; - enum sphw_api_cmd_chain_type chain_type, i; - int err; - - attr.hwdev = hwdev; - attr.num_cells = API_CHAIN_NUM_CELLS; - attr.cell_size = API_CHAIN_CELL_SIZE; - attr.rsp_size = API_CHAIN_RSP_DATA_SIZE; - - chain_type = SPHW_API_CMD_WRITE_TO_MGMT_CPU; - for (; chain_type < SPHW_API_CMD_MAX; chain_type++) { - attr.chain_type = chain_type; - - err = api_cmd_create_chain(&chain[chain_type], &attr); - if (err) { - sdk_err(dev, "Failed to create chain %d\n", chain_type); - goto create_chain_err; - } - } - - return 0; - -create_chain_err: - i = SPHW_API_CMD_WRITE_TO_MGMT_CPU; - for (; i < chain_type; i++) - api_cmd_destroy_chain(chain[i]); - - return err; -} - -/** - * sphw_api_cmd_free - free the API CMD chains - * @chain: the API CMD chains that will be freed - **/ -void sphw_api_cmd_free(struct sphw_api_cmd_chain **chain) -{ - enum sphw_api_cmd_chain_type chain_type; - - chain_type = SPHW_API_CMD_WRITE_TO_MGMT_CPU; - - for (; chain_type < SPHW_API_CMD_MAX; chain_type++) - api_cmd_destroy_chain(chain[chain_type]); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.h deleted file mode 100644 index 14a6c0b50e17..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_api_cmd.h +++ /dev/null @@ -1,277 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_API_CMD_H -#define SPHW_API_CMD_H - -#include "sphw_hwif.h" - -/*api_cmd_cell.ctrl structure*/ -#define SPHW_API_CMD_CELL_CTRL_CELL_LEN_SHIFT 0 -#define SPHW_API_CMD_CELL_CTRL_RD_DMA_ATTR_OFF_SHIFT 16 -#define SPHW_API_CMD_CELL_CTRL_WR_DMA_ATTR_OFF_SHIFT 24 -#define SPHW_API_CMD_CELL_CTRL_XOR_CHKSUM_SHIFT 56 - -#define SPHW_API_CMD_CELL_CTRL_CELL_LEN_MASK 0x3FU -#define SPHW_API_CMD_CELL_CTRL_RD_DMA_ATTR_OFF_MASK 0x3FU -#define SPHW_API_CMD_CELL_CTRL_WR_DMA_ATTR_OFF_MASK 0x3FU -#define SPHW_API_CMD_CELL_CTRL_XOR_CHKSUM_MASK 0xFFU - -#define SPHW_API_CMD_CELL_CTRL_SET(val, member) \ - ((((u64)(val)) & SPHW_API_CMD_CELL_CTRL_##member##_MASK) << \ - SPHW_API_CMD_CELL_CTRL_##member##_SHIFT) - -/*api_cmd_cell.desc structure*/ -#define SPHW_API_CMD_DESC_API_TYPE_SHIFT 0 -#define SPHW_API_CMD_DESC_RD_WR_SHIFT 1 -#define SPHW_API_CMD_DESC_MGMT_BYPASS_SHIFT 2 -#define SPHW_API_CMD_DESC_RESP_AEQE_EN_SHIFT 3 -#define SPHW_API_CMD_DESC_APICHN_RSVD_SHIFT 4 -#define SPHW_API_CMD_DESC_APICHN_CODE_SHIFT 6 -#define SPHW_API_CMD_DESC_PRIV_DATA_SHIFT 8 -#define SPHW_API_CMD_DESC_DEST_SHIFT 32 -#define SPHW_API_CMD_DESC_SIZE_SHIFT 40 -#define SPHW_API_CMD_DESC_XOR_CHKSUM_SHIFT 56 - -#define SPHW_API_CMD_DESC_API_TYPE_MASK 0x1U -#define SPHW_API_CMD_DESC_RD_WR_MASK 0x1U -#define SPHW_API_CMD_DESC_MGMT_BYPASS_MASK 0x1U -#define SPHW_API_CMD_DESC_RESP_AEQE_EN_MASK 0x1U -#define SPHW_API_CMD_DESC_APICHN_RSVD_MASK 0x3U -#define SPHW_API_CMD_DESC_APICHN_CODE_MASK 0x3U -#define SPHW_API_CMD_DESC_PRIV_DATA_MASK 0xFFFFFFU -#define SPHW_API_CMD_DESC_DEST_MASK 0x1FU -#define SPHW_API_CMD_DESC_SIZE_MASK 0x7FFU -#define SPHW_API_CMD_DESC_XOR_CHKSUM_MASK 0xFFU - -#define SPHW_API_CMD_DESC_SET(val, member) \ - ((((u64)(val)) & SPHW_API_CMD_DESC_##member##_MASK) << \ - SPHW_API_CMD_DESC_##member##_SHIFT) - -/*api_cmd_status header*/ -#define SPHW_API_CMD_STATUS_HEADER_VALID_SHIFT 0 -#define SPHW_API_CMD_STATUS_HEADER_CHAIN_ID_SHIFT 16 - -#define SPHW_API_CMD_STATUS_HEADER_VALID_MASK 0xFFU -#define SPHW_API_CMD_STATUS_HEADER_CHAIN_ID_MASK 0xFFU - -#define SPHW_API_CMD_STATUS_HEADER_GET(val, member) \ - (((val) >> SPHW_API_CMD_STATUS_HEADER_##member##_SHIFT) & \ - SPHW_API_CMD_STATUS_HEADER_##member##_MASK) - -/*API_CHAIN_REQ CSR: 0x0020+api_idx*0x080*/ -#define SPHW_API_CMD_CHAIN_REQ_RESTART_SHIFT 1 -#define SPHW_API_CMD_CHAIN_REQ_WB_TRIGGER_SHIFT 2 - -#define SPHW_API_CMD_CHAIN_REQ_RESTART_MASK 0x1U -#define SPHW_API_CMD_CHAIN_REQ_WB_TRIGGER_MASK 0x1U - -#define SPHW_API_CMD_CHAIN_REQ_SET(val, member) \ - (((val) & SPHW_API_CMD_CHAIN_REQ_##member##_MASK) << \ - SPHW_API_CMD_CHAIN_REQ_##member##_SHIFT) - -#define SPHW_API_CMD_CHAIN_REQ_GET(val, member) \ - (((val) >> SPHW_API_CMD_CHAIN_REQ_##member##_SHIFT) & \ - SPHW_API_CMD_CHAIN_REQ_##member##_MASK) - -#define SPHW_API_CMD_CHAIN_REQ_CLEAR(val, member) \ - ((val) & (~(SPHW_API_CMD_CHAIN_REQ_##member##_MASK \ - << SPHW_API_CMD_CHAIN_REQ_##member##_SHIFT))) - -/*API_CHAIN_CTL CSR: 0x0014+api_idx*0x080*/ -#define SPHW_API_CMD_CHAIN_CTRL_RESTART_EN_SHIFT 1 -#define SPHW_API_CMD_CHAIN_CTRL_XOR_ERR_SHIFT 2 -#define SPHW_API_CMD_CHAIN_CTRL_AEQE_EN_SHIFT 4 -#define SPHW_API_CMD_CHAIN_CTRL_AEQ_ID_SHIFT 8 -#define SPHW_API_CMD_CHAIN_CTRL_XOR_CHK_EN_SHIFT 28 -#define SPHW_API_CMD_CHAIN_CTRL_CELL_SIZE_SHIFT 30 - -#define SPHW_API_CMD_CHAIN_CTRL_RESTART_EN_MASK 0x1U -#define SPHW_API_CMD_CHAIN_CTRL_XOR_ERR_MASK 0x1U -#define SPHW_API_CMD_CHAIN_CTRL_AEQE_EN_MASK 0x1U -#define SPHW_API_CMD_CHAIN_CTRL_AEQ_ID_MASK 0x3U -#define SPHW_API_CMD_CHAIN_CTRL_XOR_CHK_EN_MASK 0x3U -#define SPHW_API_CMD_CHAIN_CTRL_CELL_SIZE_MASK 0x3U - -#define SPHW_API_CMD_CHAIN_CTRL_SET(val, member) \ - (((val) & SPHW_API_CMD_CHAIN_CTRL_##member##_MASK) << \ - SPHW_API_CMD_CHAIN_CTRL_##member##_SHIFT) - -#define SPHW_API_CMD_CHAIN_CTRL_CLEAR(val, member) \ - ((val) & (~(SPHW_API_CMD_CHAIN_CTRL_##member##_MASK \ - << SPHW_API_CMD_CHAIN_CTRL_##member##_SHIFT))) - -/*api_cmd rsp header*/ -#define SPHW_API_CMD_RESP_HEAD_VALID_SHIFT 0 -#define SPHW_API_CMD_RESP_HEAD_STATUS_SHIFT 8 -#define SPHW_API_CMD_RESP_HEAD_CHAIN_ID_SHIFT 16 -#define SPHW_API_CMD_RESP_HEAD_RESP_LEN_SHIFT 24 -#define SPHW_API_CMD_RESP_HEAD_DRIVER_PRIV_SHIFT 40 - -#define SPHW_API_CMD_RESP_HEAD_VALID_MASK 0xFF -#define SPHW_API_CMD_RESP_HEAD_STATUS_MASK 0xFFU -#define SPHW_API_CMD_RESP_HEAD_CHAIN_ID_MASK 0xFFU -#define SPHW_API_CMD_RESP_HEAD_RESP_LEN_MASK 0x1FFU -#define SPHW_API_CMD_RESP_HEAD_DRIVER_PRIV_MASK 0xFFFFFFU - -#define SPHW_API_CMD_RESP_HEAD_VALID_CODE 0xFF - -#define SPHW_API_CMD_RESP_HEADER_VALID(val) \ - (((val) & SPHW_API_CMD_RESP_HEAD_VALID_MASK) == \ - SPHW_API_CMD_RESP_HEAD_VALID_CODE) - -#define SPHW_API_CMD_RESP_HEAD_GET(val, member) \ - (((val) >> SPHW_API_CMD_RESP_HEAD_##member##_SHIFT) & \ - SPHW_API_CMD_RESP_HEAD_##member##_MASK) - -#define SPHW_API_CMD_RESP_HEAD_CHAIN_ID(val) \ - (((val) >> SPHW_API_CMD_RESP_HEAD_CHAIN_ID_SHIFT) & \ - SPHW_API_CMD_RESP_HEAD_CHAIN_ID_MASK) - -#define SPHW_API_CMD_RESP_HEAD_DRIVER_PRIV(val) \ - ((u16)(((val) >> SPHW_API_CMD_RESP_HEAD_DRIVER_PRIV_SHIFT) & \ - SPHW_API_CMD_RESP_HEAD_DRIVER_PRIV_MASK)) -/*API_STATUS_0 CSR: 0x0030+api_idx*0x080*/ -#define SPHW_API_CMD_STATUS_CONS_IDX_MASK 0xFFFFFFU -#define SPHW_API_CMD_STATUS_CONS_IDX_SHIFT 0 - -#define SPHW_API_CMD_STATUS_FSM_MASK 0xFU -#define SPHW_API_CMD_STATUS_FSM_SHIFT 24 - -#define SPHW_API_CMD_STATUS_CHKSUM_ERR_MASK 0x3U -#define SPHW_API_CMD_STATUS_CHKSUM_ERR_SHIFT 28 - -#define SPHW_API_CMD_STATUS_CPLD_ERR_MASK 0x1U -#define SPHW_API_CMD_STATUS_CPLD_ERR_SHIFT 30 - -#define SPHW_API_CMD_STATUS_CONS_IDX(val) \ - ((val) & SPHW_API_CMD_STATUS_CONS_IDX_MASK) - -#define SPHW_API_CMD_STATUS_CHKSUM_ERR(val) \ - (((val) >> SPHW_API_CMD_STATUS_CHKSUM_ERR_SHIFT) & \ - SPHW_API_CMD_STATUS_CHKSUM_ERR_MASK) - -#define SPHW_API_CMD_STATUS_GET(val, member) \ - (((val) >> SPHW_API_CMD_STATUS_##member##_SHIFT) & \ - SPHW_API_CMD_STATUS_##member##_MASK) - -enum sphw_api_cmd_chain_type { - /* write to mgmt cpu command with completion */ - SPHW_API_CMD_WRITE_TO_MGMT_CPU = 2, - /* multi read command with completion notification - not used */ - SPHW_API_CMD_MULTI_READ = 3, - /* write command without completion notification */ - SPHW_API_CMD_POLL_WRITE = 4, - /* read command without completion notification */ - SPHW_API_CMD_POLL_READ = 5, - /* read from mgmt cpu command with completion */ - SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU = 6, - SPHW_API_CMD_MAX, -}; - -struct sphw_api_cmd_status { - u64 header; - u32 buf_desc; - u32 cell_addr_hi; - u32 cell_addr_lo; - u32 rsvd0; - u64 rsvd1; -}; - -/* HW struct */ -struct sphw_api_cmd_cell { - u64 ctrl; - - /* address is 64 bit in HW struct */ - u64 next_cell_paddr; - - u64 desc; - - /* HW struct */ - union { - struct { - u64 hw_cmd_paddr; - } write; - - struct { - u64 hw_wb_resp_paddr; - u64 hw_cmd_paddr; - } read; - }; -}; - -struct sphw_api_cmd_resp_fmt { - u64 header; - u64 resp_data; -}; - -struct sphw_api_cmd_cell_ctxt { - struct sphw_api_cmd_cell *cell_vaddr; - - void *api_cmd_vaddr; - - struct sphw_api_cmd_resp_fmt *resp; - - struct completion done; - int status; - - u32 saved_prod_idx; -}; - -struct sphw_api_cmd_chain_attr { - struct sphw_hwdev *hwdev; - enum sphw_api_cmd_chain_type chain_type; - - u32 num_cells; - u16 rsp_size; - u16 cell_size; -}; - -struct sphw_api_cmd_chain { - struct sphw_hwdev *hwdev; - enum sphw_api_cmd_chain_type chain_type; - - u32 num_cells; - u16 cell_size; - u16 rsp_size; - - /* HW members is 24 bit format */ - u32 prod_idx; - u32 cons_idx; - - struct semaphore sem; - /* Async cmd can not be scheduling */ - spinlock_t async_lock; - - dma_addr_t wb_status_paddr; - struct sphw_api_cmd_status *wb_status; - - dma_addr_t head_cell_paddr; - struct sphw_api_cmd_cell *head_node; - - struct sphw_api_cmd_cell_ctxt *cell_ctxt; - struct sphw_api_cmd_cell *curr_node; - - struct sphw_dma_addr_align cells_addr; - - u8 *cell_vaddr_base; - u64 cell_paddr_base; - u8 *rsp_vaddr_base; - u64 rsp_paddr_base; - u8 *buf_vaddr_base; - u64 buf_paddr_base; - u64 cell_size_align; - u64 rsp_size_align; - u64 buf_size_align; -}; - -int sphw_api_cmd_write(struct sphw_api_cmd_chain *chain, u8 node_id, const void *cmd, u16 size); - -int sphw_api_cmd_read(struct sphw_api_cmd_chain *chain, u8 node_id, const void *cmd, u16 size, - void *ack, u16 ack_size); - -int sphw_api_cmd_init(struct sphw_hwdev *hwdev, struct sphw_api_cmd_chain **chain); - -void sphw_api_cmd_free(struct sphw_api_cmd_chain **chain); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h deleted file mode 100644 index 63b89e71c552..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h +++ /dev/null @@ -1,127 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_CFG_CMD_H -#define SPHW_CFG_CMD_H - -#include "sphw_mgmt_msg_base.h" - -enum cfg_cmd { - CFG_CMD_GET_DEV_CAP = 0, -}; - -struct cfg_cmd_dev_cap { - struct mgmt_msg_head head; - - u16 func_id; - u16 rsvd1; - - /* Public resources */ - u8 host_id; - u8 ep_id; - u8 er_id; - u8 port_id; - - u16 host_total_func; - u8 host_pf_num; - u8 pf_id_start; - u16 host_vf_num; - u16 vf_id_start; - u8 host_oq_id_mask_val; - u8 rsvd_host[3]; - - u16 svc_cap_en; - u16 max_vf; - u8 flexq_en; - u8 valid_cos_bitmap; - /* Reserved for func_valid_cos_bitmap */ - u16 rsvd_func1; - u32 rsvd_func2; - - u8 sf_svc_attr; - u8 func_sf_en; - u8 lb_mode; - u8 smf_pg; - - u32 max_conn_num; - u16 max_stick2cache_num; - u16 max_bfilter_start_addr; - u16 bfilter_len; - u16 hash_bucket_num; - - /* shared resource */ - u8 host_sf_en; - u8 rsvd2_sr[3]; - u32 host_pctx_num; - u32 host_ccxt_num; - u32 host_scq_num; - u32 host_srq_num; - u32 host_mpt_num; - - /* l2nic */ - u16 nic_max_sq_id; - u16 nic_max_rq_id; - u32 rsvd_nic[3]; - - /* RoCE */ - u32 roce_max_qp; - u32 roce_max_cq; - u32 roce_max_srq; - u32 roce_max_mpt; - u32 roce_max_drc_qp; - - u32 roce_cmtt_cl_start; - u32 roce_cmtt_cl_end; - u32 roce_cmtt_cl_size; - - u32 roce_dmtt_cl_start; - u32 roce_dmtt_cl_end; - u32 roce_dmtt_cl_size; - - u32 roce_wqe_cl_start; - u32 roce_wqe_cl_end; - u32 roce_wqe_cl_size; - u8 roce_srq_container_mode; - u8 rsvd_roce1[3]; - u32 rsvd_roce2[5]; - - /* IPsec */ - u32 ipsec_max_sactx; - u32 rsvd_ipsec[3]; - - /* OVS */ - u32 ovs_max_qpc; - u16 fake_vf_start_id; - u8 fake_vf_num; - u8 rsvd_ovs1; - u32 rsvd_ovs2[2]; - - /* ToE */ - u32 toe_max_pctx; - u32 toe_max_cq; - u16 toe_max_srq; - u16 toe_srq_id_start; - u16 toe_max_mpt; - u16 toe_max_cctxt; - u32 rsvd_toe[2]; - - /* FC */ - u32 fc_max_pctx; - u32 fc_max_scq; - u32 fc_max_srq; - - u32 fc_max_cctx; - u32 fc_cctx_id_start; - - u8 fc_vp_id_start; - u8 fc_vp_id_end; - u8 rsvd_fc1[2]; - u32 rsvd_fc2[5]; - - /* VBS */ - u32 rsvd_vbs[4]; - - u32 rsvd_glb[11]; -}; - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cmdq.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cmdq.c deleted file mode 100644 index 9ebff6f8ac97..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cmdq.c +++ /dev/null @@ -1,1573 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/errno.h> -#include <linux/completion.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/spinlock.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/delay.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_hwdev.h" -#include "sphw_eqs.h" -#include "sphw_common.h" -#include "sphw_wq.h" -#include "sphw_hw_comm.h" -#include "sphw_cmdq.h" - -#define SPHW_CMDQ_BUF_SIZE 2048U -#define SPHW_CMDQ_BUF_HW_RSVD 8 -#define SPHW_CMDQ_MAX_DATA_SIZE \ - (SPHW_CMDQ_BUF_SIZE - SPHW_CMDQ_BUF_HW_RSVD) - -#define CMDQ_CMD_TIMEOUT 5000 /* millisecond */ - -#define UPPER_8_BITS(data) (((data) >> 8) & 0xFF) -#define LOWER_8_BITS(data) ((data) & 0xFF) - -#define CMDQ_DB_INFO_HI_PROD_IDX_SHIFT 0 -#define CMDQ_DB_INFO_HI_PROD_IDX_MASK 0xFFU -#define CMDQ_DB_INFO_SET(val, member) \ - ((((u32)(val)) & CMDQ_DB_INFO_##member##_MASK) << \ - CMDQ_DB_INFO_##member##_SHIFT) - -#define CMDQ_DB_HEAD_QUEUE_TYPE_SHIFT 23 -#define CMDQ_DB_HEAD_CMDQ_TYPE_SHIFT 24 -#define CMDQ_DB_HEAD_SRC_TYPE_SHIFT 27 -#define CMDQ_DB_HEAD_QUEUE_TYPE_MASK 0x1U -#define CMDQ_DB_HEAD_CMDQ_TYPE_MASK 0x7U -#define CMDQ_DB_HEAD_SRC_TYPE_MASK 0x1FU -#define CMDQ_DB_HEAD_SET(val, member) \ - ((((u32)(val)) & CMDQ_DB_HEAD_##member##_MASK) << \ - CMDQ_DB_HEAD_##member##_SHIFT) - -#define CMDQ_CTRL_PI_SHIFT 0 -#define CMDQ_CTRL_CMD_SHIFT 16 -#define CMDQ_CTRL_MOD_SHIFT 24 -#define CMDQ_CTRL_ACK_TYPE_SHIFT 29 -#define CMDQ_CTRL_HW_BUSY_BIT_SHIFT 31 - -#define CMDQ_CTRL_PI_MASK 0xFFFFU -#define CMDQ_CTRL_CMD_MASK 0xFFU -#define CMDQ_CTRL_MOD_MASK 0x1FU -#define CMDQ_CTRL_ACK_TYPE_MASK 0x3U -#define CMDQ_CTRL_HW_BUSY_BIT_MASK 0x1U - -#define CMDQ_CTRL_SET(val, member) \ - ((((u32)(val)) & CMDQ_CTRL_##member##_MASK) << \ - CMDQ_CTRL_##member##_SHIFT) - -#define CMDQ_CTRL_GET(val, member) \ - (((val) >> CMDQ_CTRL_##member##_SHIFT) & \ - CMDQ_CTRL_##member##_MASK) - -#define CMDQ_WQE_HEADER_BUFDESC_LEN_SHIFT 0 -#define CMDQ_WQE_HEADER_COMPLETE_FMT_SHIFT 15 -#define CMDQ_WQE_HEADER_DATA_FMT_SHIFT 22 -#define CMDQ_WQE_HEADER_COMPLETE_REQ_SHIFT 23 -#define CMDQ_WQE_HEADER_COMPLETE_SECT_LEN_SHIFT 27 -#define CMDQ_WQE_HEADER_CTRL_LEN_SHIFT 29 -#define CMDQ_WQE_HEADER_HW_BUSY_BIT_SHIFT 31 - -#define CMDQ_WQE_HEADER_BUFDESC_LEN_MASK 0xFFU -#define CMDQ_WQE_HEADER_COMPLETE_FMT_MASK 0x1U -#define CMDQ_WQE_HEADER_DATA_FMT_MASK 0x1U -#define CMDQ_WQE_HEADER_COMPLETE_REQ_MASK 0x1U -#define CMDQ_WQE_HEADER_COMPLETE_SECT_LEN_MASK 0x3U -#define CMDQ_WQE_HEADER_CTRL_LEN_MASK 0x3U -#define CMDQ_WQE_HEADER_HW_BUSY_BIT_MASK 0x1U - -#define CMDQ_WQE_HEADER_SET(val, member) \ - ((((u32)(val)) & CMDQ_WQE_HEADER_##member##_MASK) << \ - CMDQ_WQE_HEADER_##member##_SHIFT) - -#define CMDQ_WQE_HEADER_GET(val, member) \ - (((val) >> CMDQ_WQE_HEADER_##member##_SHIFT) & \ - CMDQ_WQE_HEADER_##member##_MASK) - -#define CMDQ_CTXT_CURR_WQE_PAGE_PFN_SHIFT 0 -#define CMDQ_CTXT_EQ_ID_SHIFT 53 -#define CMDQ_CTXT_CEQ_ARM_SHIFT 61 -#define CMDQ_CTXT_CEQ_EN_SHIFT 62 -#define CMDQ_CTXT_HW_BUSY_BIT_SHIFT 63 - -#define CMDQ_CTXT_CURR_WQE_PAGE_PFN_MASK 0xFFFFFFFFFFFFF -#define CMDQ_CTXT_EQ_ID_MASK 0xFF -#define CMDQ_CTXT_CEQ_ARM_MASK 0x1 -#define CMDQ_CTXT_CEQ_EN_MASK 0x1 -#define CMDQ_CTXT_HW_BUSY_BIT_MASK 0x1 - -#define CMDQ_CTXT_PAGE_INFO_SET(val, member) \ - (((u64)(val) & CMDQ_CTXT_##member##_MASK) << \ - CMDQ_CTXT_##member##_SHIFT) - -#define CMDQ_CTXT_PAGE_INFO_GET(val, member) \ - (((u64)(val) >> CMDQ_CTXT_##member##_SHIFT) & \ - CMDQ_CTXT_##member##_MASK) - -#define CMDQ_CTXT_WQ_BLOCK_PFN_SHIFT 0 -#define CMDQ_CTXT_CI_SHIFT 52 - -#define CMDQ_CTXT_WQ_BLOCK_PFN_MASK 0xFFFFFFFFFFFFF -#define CMDQ_CTXT_CI_MASK 0xFFF - -#define CMDQ_CTXT_BLOCK_INFO_SET(val, member) \ - (((u64)(val) & CMDQ_CTXT_##member##_MASK) << \ - CMDQ_CTXT_##member##_SHIFT) - -#define CMDQ_CTXT_BLOCK_INFO_GET(val, member) \ - (((u64)(val) >> CMDQ_CTXT_##member##_SHIFT) & \ - CMDQ_CTXT_##member##_MASK) - -#define SAVED_DATA_ARM_SHIFT 31 - -#define SAVED_DATA_ARM_MASK 0x1U - -#define SAVED_DATA_SET(val, member) \ - (((val) & SAVED_DATA_##member##_MASK) << \ - SAVED_DATA_##member##_SHIFT) - -#define SAVED_DATA_CLEAR(val, member) \ - ((val) & (~(SAVED_DATA_##member##_MASK << \ - SAVED_DATA_##member##_SHIFT))) - -#define WQE_ERRCODE_VAL_SHIFT 0 - -#define WQE_ERRCODE_VAL_MASK 0x7FFFFFFF - -#define WQE_ERRCODE_GET(val, member) \ - (((val) >> WQE_ERRCODE_##member##_SHIFT) & \ - WQE_ERRCODE_##member##_MASK) - -#define CEQE_CMDQ_TYPE_SHIFT 0 - -#define CEQE_CMDQ_TYPE_MASK 0x7 - -#define CEQE_CMDQ_GET(val, member) \ - (((val) >> CEQE_CMDQ_##member##_SHIFT) & \ - CEQE_CMDQ_##member##_MASK) - -#define WQE_COMPLETED(ctrl_info) CMDQ_CTRL_GET(ctrl_info, HW_BUSY_BIT) - -#define WQE_HEADER(wqe) ((struct sphw_cmdq_header *)(wqe)) - -#define CMDQ_DB_PI_OFF(pi) (((u16)LOWER_8_BITS(pi)) << 3) - -#define CMDQ_DB_ADDR(db_base, pi) \ - (((u8 *)(db_base)) + CMDQ_DB_PI_OFF(pi)) - -#define CMDQ_PFN_SHIFT 12 -#define CMDQ_PFN(addr) ((addr) >> CMDQ_PFN_SHIFT) - -#define FIRST_DATA_TO_WRITE_LAST sizeof(u64) - -#define WQE_LCMD_SIZE 64 -#define WQE_SCMD_SIZE 64 - -#define COMPLETE_LEN 3 - -#define CMDQ_WQEBB_SIZE 64 -#define CMDQ_WQE_SIZE 64 - -#define cmdq_to_cmdqs(cmdq) container_of((cmdq) - (cmdq)->cmdq_type, \ - struct sphw_cmdqs, cmdq[0]) - -#define CMDQ_SEND_CMPT_CODE 10 -#define CMDQ_COMPLETE_CMPT_CODE 11 -#define CMDQ_FORCE_STOP_CMPT_CODE 12 - -enum cmdq_scmd_type { - CMDQ_SET_ARM_CMD = 2, -}; - -enum cmdq_wqe_type { - WQE_LCMD_TYPE, - WQE_SCMD_TYPE, -}; - -enum ctrl_sect_len { - CTRL_SECT_LEN = 1, - CTRL_DIRECT_SECT_LEN = 2, -}; - -enum bufdesc_len { - BUFDESC_LCMD_LEN = 2, - BUFDESC_SCMD_LEN = 3, -}; - -enum data_format { - DATA_SGE, - DATA_DIRECT, -}; - -enum completion_format { - COMPLETE_DIRECT, - COMPLETE_SGE, -}; - -enum completion_request { - CEQ_SET = 1, -}; - -enum cmdq_cmd_type { - SYNC_CMD_DIRECT_RESP, - SYNC_CMD_SGE_RESP, - ASYNC_CMD, -}; - -#define NUM_WQEBBS_FOR_CMDQ_WQE 1 - -bool sphw_cmdq_idle(struct sphw_cmdq *cmdq) -{ - return sphw_wq_is_empty(&cmdq->wq); -} - -static void *cmdq_read_wqe(struct sphw_wq *wq, u16 *ci) -{ - if (sphw_wq_is_empty(wq)) - return NULL; - - return sphw_wq_read_one_wqebb(wq, ci); -} - -static void *cmdq_get_wqe(struct sphw_wq *wq, u16 *pi) -{ - if (!sphw_wq_free_wqebbs(wq)) - return NULL; - - return sphw_wq_get_one_wqebb(wq, pi); -} - -struct sphw_cmd_buf *sphw_alloc_cmd_buf(void *hwdev) -{ - struct sphw_cmdqs *cmdqs = NULL; - struct sphw_cmd_buf *cmd_buf = NULL; - void *dev = NULL; - - if (!hwdev) { - pr_err("Failed to alloc cmd buf, Invalid hwdev\n"); - return NULL; - } - - cmdqs = ((struct sphw_hwdev *)hwdev)->cmdqs; - dev = ((struct sphw_hwdev *)hwdev)->dev_hdl; - - cmd_buf = kzalloc(sizeof(*cmd_buf), GFP_ATOMIC); - if (!cmd_buf) { - sdk_err(dev, "Failed to allocate cmd buf\n"); - return NULL; - } - - cmd_buf->buf = pci_pool_alloc(cmdqs->cmd_buf_pool, GFP_ATOMIC, - &cmd_buf->dma_addr); - if (!cmd_buf->buf) { - sdk_err(dev, "Failed to allocate cmdq cmd buf from the pool\n"); - goto alloc_pci_buf_err; - } - - atomic_set(&cmd_buf->ref_cnt, 1); - - return cmd_buf; - -alloc_pci_buf_err: - kfree(cmd_buf); - return NULL; -} - -void sphw_free_cmd_buf(void *hwdev, struct sphw_cmd_buf *cmd_buf) -{ - struct sphw_cmdqs *cmdqs = NULL; - - if (!hwdev || !cmd_buf) { - pr_err("Failed to free cmd buf: hwdev: %p, cmd_buf: %p\n", - hwdev, cmd_buf); - return; - } - - if (!atomic_dec_and_test(&cmd_buf->ref_cnt)) - return; - - cmdqs = ((struct sphw_hwdev *)hwdev)->cmdqs; - - pci_pool_free(cmdqs->cmd_buf_pool, cmd_buf->buf, cmd_buf->dma_addr); - kfree(cmd_buf); -} - -static void cmdq_set_completion(struct sphw_cmdq_completion *complete, - struct sphw_cmd_buf *buf_out) -{ - struct sphw_sge_resp *sge_resp = &complete->sge_resp; - - sphw_set_sge(&sge_resp->sge, buf_out->dma_addr, SPHW_CMDQ_BUF_SIZE); -} - -static void cmdq_set_lcmd_bufdesc(struct sphw_cmdq_wqe_lcmd *wqe, - struct sphw_cmd_buf *buf_in) -{ - sphw_set_sge(&wqe->buf_desc.sge, buf_in->dma_addr, buf_in->size); -} - -static void cmdq_set_inline_wqe_data(struct sphw_cmdq_inline_wqe *wqe, - const void *buf_in, u32 in_size) -{ - struct sphw_cmdq_wqe_scmd *wqe_scmd = &wqe->wqe_scmd; - - wqe_scmd->buf_desc.buf_len = in_size; - memcpy(wqe_scmd->buf_desc.data, buf_in, in_size); -} - -static void cmdq_fill_db(struct sphw_cmdq_db *db, - enum sphw_cmdq_type cmdq_type, u16 prod_idx) -{ - db->db_info = CMDQ_DB_INFO_SET(UPPER_8_BITS(prod_idx), HI_PROD_IDX); - - db->db_head = CMDQ_DB_HEAD_SET(SPHW_DB_CMDQ_TYPE, QUEUE_TYPE) | - CMDQ_DB_HEAD_SET(cmdq_type, CMDQ_TYPE) | - CMDQ_DB_HEAD_SET(SPHW_DB_SRC_CMDQ_TYPE, SRC_TYPE); -} - -static void cmdq_set_db(struct sphw_cmdq *cmdq, - enum sphw_cmdq_type cmdq_type, u16 prod_idx) -{ - struct sphw_cmdq_db db = {0}; - - cmdq_fill_db(&db, cmdq_type, prod_idx); - - wmb(); /* write all before the doorbell */ - writeq(*((u64 *)&db), CMDQ_DB_ADDR(cmdq->db_base, prod_idx)); -} - -static void cmdq_wqe_fill(void *dst, const void *src) -{ - memcpy((u8 *)dst + FIRST_DATA_TO_WRITE_LAST, - (u8 *)src + FIRST_DATA_TO_WRITE_LAST, - CMDQ_WQE_SIZE - FIRST_DATA_TO_WRITE_LAST); - - wmb(); /* The first 8 bytes should be written last */ - - *(u64 *)dst = *(u64 *)src; -} - -static void cmdq_prepare_wqe_ctrl(struct sphw_cmdq_wqe *wqe, int wrapped, - u8 mod, u8 cmd, u16 prod_idx, - enum completion_format complete_format, - enum data_format data_format, - enum bufdesc_len buf_len) -{ - struct sphw_ctrl *ctrl = NULL; - enum ctrl_sect_len ctrl_len; - struct sphw_cmdq_wqe_lcmd *wqe_lcmd = NULL; - struct sphw_cmdq_wqe_scmd *wqe_scmd = NULL; - u32 saved_data = WQE_HEADER(wqe)->saved_data; - - if (data_format == DATA_SGE) { - wqe_lcmd = &wqe->wqe_lcmd; - - wqe_lcmd->status.status_info = 0; - ctrl = &wqe_lcmd->ctrl; - ctrl_len = CTRL_SECT_LEN; - } else { - wqe_scmd = &wqe->inline_wqe.wqe_scmd; - - wqe_scmd->status.status_info = 0; - ctrl = &wqe_scmd->ctrl; - ctrl_len = CTRL_DIRECT_SECT_LEN; - } - - ctrl->ctrl_info = CMDQ_CTRL_SET(prod_idx, PI) | - CMDQ_CTRL_SET(cmd, CMD) | - CMDQ_CTRL_SET(mod, MOD); - - WQE_HEADER(wqe)->header_info = - CMDQ_WQE_HEADER_SET(buf_len, BUFDESC_LEN) | - CMDQ_WQE_HEADER_SET(complete_format, COMPLETE_FMT) | - CMDQ_WQE_HEADER_SET(data_format, DATA_FMT) | - CMDQ_WQE_HEADER_SET(CEQ_SET, COMPLETE_REQ) | - CMDQ_WQE_HEADER_SET(COMPLETE_LEN, COMPLETE_SECT_LEN) | - CMDQ_WQE_HEADER_SET(ctrl_len, CTRL_LEN) | - CMDQ_WQE_HEADER_SET((u32)wrapped, HW_BUSY_BIT); - - if (cmd == CMDQ_SET_ARM_CMD && mod == SPHW_MOD_COMM) { - saved_data &= SAVED_DATA_CLEAR(saved_data, ARM); - WQE_HEADER(wqe)->saved_data = saved_data | - SAVED_DATA_SET(1, ARM); - } else { - saved_data &= SAVED_DATA_CLEAR(saved_data, ARM); - WQE_HEADER(wqe)->saved_data = saved_data; - } -} - -static void cmdq_set_lcmd_wqe(struct sphw_cmdq_wqe *wqe, - enum cmdq_cmd_type cmd_type, - struct sphw_cmd_buf *buf_in, - struct sphw_cmd_buf *buf_out, int wrapped, - u8 mod, u8 cmd, u16 prod_idx) -{ - struct sphw_cmdq_wqe_lcmd *wqe_lcmd = &wqe->wqe_lcmd; - enum completion_format complete_format = COMPLETE_DIRECT; - - switch (cmd_type) { - case SYNC_CMD_DIRECT_RESP: - wqe_lcmd->completion.direct_resp = 0; - break; - case SYNC_CMD_SGE_RESP: - if (buf_out) { - complete_format = COMPLETE_SGE; - cmdq_set_completion(&wqe_lcmd->completion, - buf_out); - } - break; - case ASYNC_CMD: - wqe_lcmd->completion.direct_resp = 0; - wqe_lcmd->buf_desc.saved_async_buf = (u64)(buf_in); - break; - } - - cmdq_prepare_wqe_ctrl(wqe, wrapped, mod, cmd, prod_idx, complete_format, - DATA_SGE, BUFDESC_LCMD_LEN); - - cmdq_set_lcmd_bufdesc(wqe_lcmd, buf_in); -} - -static void cmdq_set_inline_wqe(struct sphw_cmdq_wqe *wqe, - enum cmdq_cmd_type cmd_type, - const void *buf_in, u16 in_size, - struct sphw_cmd_buf *buf_out, int wrapped, - u8 mod, u8 cmd, u16 prod_idx) -{ - struct sphw_cmdq_wqe_scmd *wqe_scmd = &wqe->inline_wqe.wqe_scmd; - enum completion_format complete_format = COMPLETE_DIRECT; - - switch (cmd_type) { - case SYNC_CMD_SGE_RESP: - complete_format = COMPLETE_SGE; - cmdq_set_completion(&wqe_scmd->completion, buf_out); - break; - case SYNC_CMD_DIRECT_RESP: - complete_format = COMPLETE_DIRECT; - wqe_scmd->completion.direct_resp = 0; - break; - default: - break; - } - - cmdq_prepare_wqe_ctrl(wqe, wrapped, mod, cmd, prod_idx, - complete_format, DATA_DIRECT, BUFDESC_SCMD_LEN); - - cmdq_set_inline_wqe_data(&wqe->inline_wqe, buf_in, in_size); -} - -static void cmdq_update_cmd_status(struct sphw_cmdq *cmdq, u16 prod_idx, - struct sphw_cmdq_wqe *wqe) -{ - struct sphw_cmdq_cmd_info *cmd_info; - struct sphw_cmdq_wqe_lcmd *wqe_lcmd; - u32 status_info; - - wqe_lcmd = &wqe->wqe_lcmd; - cmd_info = &cmdq->cmd_infos[prod_idx]; - - if (cmd_info->errcode) { - status_info = wqe_lcmd->status.status_info; - *cmd_info->errcode = WQE_ERRCODE_GET(status_info, VAL); - } - - if (cmd_info->direct_resp) - *cmd_info->direct_resp = wqe_lcmd->completion.direct_resp; -} - -static int sphw_cmdq_sync_timeout_check(struct sphw_cmdq *cmdq, struct sphw_cmdq_wqe *wqe, u16 pi) -{ - struct sphw_cmdq_wqe_lcmd *wqe_lcmd; - u32 ctrl_info; - - wqe_lcmd = &wqe->wqe_lcmd; - ctrl_info = wqe_lcmd->ctrl.ctrl_info; - if (!WQE_COMPLETED(ctrl_info)) { - sdk_info(cmdq->hwdev->dev_hdl, "Cmdq sync command check busy bit not set\n"); - return -EFAULT; - } - - cmdq_update_cmd_status(cmdq, pi, wqe); - - sdk_info(cmdq->hwdev->dev_hdl, "Cmdq sync command check succeed\n"); - return 0; -} - -static void clear_cmd_info(struct sphw_cmdq_cmd_info *cmd_info, - struct sphw_cmdq_cmd_info *saved_cmd_info) -{ - if (cmd_info->errcode == saved_cmd_info->errcode) - cmd_info->errcode = NULL; - - if (cmd_info->done == saved_cmd_info->done) - cmd_info->done = NULL; - - if (cmd_info->direct_resp == saved_cmd_info->direct_resp) - cmd_info->direct_resp = NULL; -} - -static int cmdq_ceq_handler_status(struct sphw_cmdq *cmdq, - struct sphw_cmdq_cmd_info *cmd_info, - struct sphw_cmdq_cmd_info *saved_cmd_info, - u64 curr_msg_id, u16 curr_prod_idx, - struct sphw_cmdq_wqe *curr_wqe, - u32 timeout) -{ - ulong timeo; - int err; - - timeo = msecs_to_jiffies(timeout); - if (wait_for_completion_timeout(saved_cmd_info->done, timeo)) - return 0; - - spin_lock_bh(&cmdq->cmdq_lock); - - if (cmd_info->cmpt_code == saved_cmd_info->cmpt_code) - cmd_info->cmpt_code = NULL; - - if (*saved_cmd_info->cmpt_code == CMDQ_COMPLETE_CMPT_CODE) { - sdk_info(cmdq->hwdev->dev_hdl, "Cmdq direct sync command has been completed\n"); - spin_unlock_bh(&cmdq->cmdq_lock); - return 0; - } - - if (curr_msg_id == cmd_info->cmdq_msg_id) { - err = sphw_cmdq_sync_timeout_check(cmdq, curr_wqe, curr_prod_idx); - if (err) - cmd_info->cmd_type = SPHW_CMD_TYPE_TIMEOUT; - else - cmd_info->cmd_type = SPHW_CMD_TYPE_FAKE_TIMEOUT; - } else { - err = -ETIMEDOUT; - sdk_err(cmdq->hwdev->dev_hdl, "Cmdq sync command current msg id dismatch with cmd_info msg id\n"); - } - - clear_cmd_info(cmd_info, saved_cmd_info); - - spin_unlock_bh(&cmdq->cmdq_lock); - - if (!err) - return 0; - - sphw_dump_ceq_info(cmdq->hwdev); - - return -ETIMEDOUT; -} - -static int wait_cmdq_sync_cmd_completion(struct sphw_cmdq *cmdq, - struct sphw_cmdq_cmd_info *cmd_info, - struct sphw_cmdq_cmd_info *saved_cmd_info, - u64 curr_msg_id, u16 curr_prod_idx, - struct sphw_cmdq_wqe *curr_wqe, u32 timeout) -{ - return cmdq_ceq_handler_status(cmdq, cmd_info, saved_cmd_info, - curr_msg_id, curr_prod_idx, - curr_wqe, timeout); -} - -static int cmdq_msg_lock(struct sphw_cmdq *cmdq, u16 channel) -{ - struct sphw_cmdqs *cmdqs = cmdq_to_cmdqs(cmdq); - - /* Keep wrapped and doorbell index correct. bh - for tasklet(ceq) */ - spin_lock_bh(&cmdq->cmdq_lock); - - if (cmdqs->lock_channel_en && test_bit(channel, &cmdqs->channel_stop)) { - spin_unlock_bh(&cmdq->cmdq_lock); - return -EAGAIN; - } - - return 0; -} - -static void cmdq_msg_unlock(struct sphw_cmdq *cmdq) -{ - spin_unlock_bh(&cmdq->cmdq_lock); -} - -static void cmdq_clear_cmd_buf(struct sphw_cmdq_cmd_info *cmd_info, - struct sphw_hwdev *hwdev) -{ - if (cmd_info->buf_in) - sphw_free_cmd_buf(hwdev, cmd_info->buf_in); - - if (cmd_info->buf_out) - sphw_free_cmd_buf(hwdev, cmd_info->buf_out); - - cmd_info->buf_in = NULL; - cmd_info->buf_out = NULL; -} - -static void cmdq_set_cmd_buf(struct sphw_cmdq_cmd_info *cmd_info, - struct sphw_hwdev *hwdev, - struct sphw_cmd_buf *buf_in, - struct sphw_cmd_buf *buf_out) -{ - cmd_info->buf_in = buf_in; - cmd_info->buf_out = buf_out; - - if (buf_in) - atomic_inc(&buf_in->ref_cnt); - - if (buf_out) - atomic_inc(&buf_out->ref_cnt); -} - -static int cmdq_sync_cmd_direct_resp(struct sphw_cmdq *cmdq, u8 mod, - u8 cmd, struct sphw_cmd_buf *buf_in, - u64 *out_param, u32 timeout, u16 channel) -{ - struct sphw_wq *wq = &cmdq->wq; - struct sphw_cmdq_wqe *curr_wqe = NULL, wqe; - struct sphw_cmdq_cmd_info *cmd_info = NULL, saved_cmd_info; - struct completion done; - u16 curr_prod_idx, next_prod_idx; - int wrapped, errcode = 0; - int cmpt_code = CMDQ_SEND_CMPT_CODE; - u64 curr_msg_id; - int err; - - err = cmdq_msg_lock(cmdq, channel); - if (err) - return err; - - curr_wqe = cmdq_get_wqe(wq, &curr_prod_idx); - if (!curr_wqe) { - cmdq_msg_unlock(cmdq); - return -EBUSY; - } - - memset(&wqe, 0, sizeof(wqe)); - - wrapped = cmdq->wrapped; - - next_prod_idx = curr_prod_idx + NUM_WQEBBS_FOR_CMDQ_WQE; - if (next_prod_idx >= wq->q_depth) { - cmdq->wrapped = !cmdq->wrapped; - next_prod_idx -= (u16)wq->q_depth; - } - - cmd_info = &cmdq->cmd_infos[curr_prod_idx]; - - init_completion(&done); - - cmd_info->cmd_type = SPHW_CMD_TYPE_DIRECT_RESP; - cmd_info->done = &done; - cmd_info->errcode = &errcode; - cmd_info->direct_resp = out_param; - cmd_info->cmpt_code = &cmpt_code; - cmd_info->channel = channel; - cmdq_set_cmd_buf(cmd_info, cmdq->hwdev, buf_in, NULL); - - memcpy(&saved_cmd_info, cmd_info, sizeof(*cmd_info)); - - cmdq_set_lcmd_wqe(&wqe, SYNC_CMD_DIRECT_RESP, buf_in, NULL, - wrapped, mod, cmd, curr_prod_idx); - - /* CMDQ WQE is not shadow, therefore wqe will be written to wq */ - cmdq_wqe_fill(curr_wqe, &wqe); - - (cmd_info->cmdq_msg_id)++; - curr_msg_id = cmd_info->cmdq_msg_id; - - cmdq_set_db(cmdq, SPHW_CMDQ_SYNC, next_prod_idx); - - cmdq_msg_unlock(cmdq); - - timeout = timeout ? timeout : CMDQ_CMD_TIMEOUT; - err = wait_cmdq_sync_cmd_completion(cmdq, cmd_info, &saved_cmd_info, - curr_msg_id, curr_prod_idx, - curr_wqe, timeout); - if (err) { - sdk_err(cmdq->hwdev->dev_hdl, "Cmdq sync command(mod: %u, cmd: %u) timeout, prod idx: 0x%x\n", - mod, cmd, curr_prod_idx); - err = -ETIMEDOUT; - } - - if (cmpt_code == CMDQ_FORCE_STOP_CMPT_CODE) { - sdk_info(cmdq->hwdev->dev_hdl, "Force stop cmdq cmd, mod: %u, cmd: %u\n", - mod, cmd); - err = -EAGAIN; - } - - smp_rmb(); /* read error code after completion */ - - return err ? err : errcode; -} - -static int cmdq_sync_cmd_detail_resp(struct sphw_cmdq *cmdq, u8 mod, u8 cmd, - struct sphw_cmd_buf *buf_in, - struct sphw_cmd_buf *buf_out, - u64 *out_param, u32 timeout, u16 channel) -{ - struct sphw_wq *wq = &cmdq->wq; - struct sphw_cmdq_wqe *curr_wqe = NULL, wqe; - struct sphw_cmdq_cmd_info *cmd_info = NULL, saved_cmd_info; - struct completion done; - u16 curr_prod_idx, next_prod_idx; - int wrapped, errcode = 0; - int cmpt_code = CMDQ_SEND_CMPT_CODE; - u64 curr_msg_id; - int err; - - err = cmdq_msg_lock(cmdq, channel); - if (err) - return err; - - curr_wqe = cmdq_get_wqe(wq, &curr_prod_idx); - if (!curr_wqe) { - cmdq_msg_unlock(cmdq); - return -EBUSY; - } - - memset(&wqe, 0, sizeof(wqe)); - - wrapped = cmdq->wrapped; - - next_prod_idx = curr_prod_idx + NUM_WQEBBS_FOR_CMDQ_WQE; - if (next_prod_idx >= wq->q_depth) { - cmdq->wrapped = !cmdq->wrapped; - next_prod_idx -= (u16)wq->q_depth; - } - - cmd_info = &cmdq->cmd_infos[curr_prod_idx]; - - init_completion(&done); - - cmd_info->cmd_type = SPHW_CMD_TYPE_SGE_RESP; - cmd_info->done = &done; - cmd_info->errcode = &errcode; - cmd_info->direct_resp = out_param; - cmd_info->cmpt_code = &cmpt_code; - cmd_info->channel = channel; - cmdq_set_cmd_buf(cmd_info, cmdq->hwdev, buf_in, buf_out); - - memcpy(&saved_cmd_info, cmd_info, sizeof(*cmd_info)); - - cmdq_set_lcmd_wqe(&wqe, SYNC_CMD_SGE_RESP, buf_in, buf_out, - wrapped, mod, cmd, curr_prod_idx); - - cmdq_wqe_fill(curr_wqe, &wqe); - - (cmd_info->cmdq_msg_id)++; - curr_msg_id = cmd_info->cmdq_msg_id; - - cmdq_set_db(cmdq, cmdq->cmdq_type, next_prod_idx); - - cmdq_msg_unlock(cmdq); - - timeout = timeout ? timeout : CMDQ_CMD_TIMEOUT; - err = wait_cmdq_sync_cmd_completion(cmdq, cmd_info, &saved_cmd_info, - curr_msg_id, curr_prod_idx, - curr_wqe, timeout); - if (err) { - sdk_err(cmdq->hwdev->dev_hdl, "Cmdq sync command(mod: %u, cmd: %u) timeout, prod idx: 0x%x\n", - mod, cmd, curr_prod_idx); - err = -ETIMEDOUT; - } - - if (cmpt_code == CMDQ_FORCE_STOP_CMPT_CODE) { - sdk_info(cmdq->hwdev->dev_hdl, "Force stop cmdq cmd, mod: %u, cmd: %u\n", - mod, cmd); - err = -EAGAIN; - } - - smp_rmb(); /* read error code after completion */ - - return err ? err : errcode; -} - -static int cmdq_async_cmd(struct sphw_cmdq *cmdq, u8 mod, u8 cmd, - struct sphw_cmd_buf *buf_in, u16 channel) -{ - struct sphw_cmdq_cmd_info *cmd_info = NULL; - struct sphw_wq *wq = &cmdq->wq; - u16 curr_prod_idx, next_prod_idx; - struct sphw_cmdq_wqe *curr_wqe = NULL, wqe; - int wrapped, err; - - err = cmdq_msg_lock(cmdq, channel); - if (err) - return err; - - curr_wqe = cmdq_get_wqe(wq, &curr_prod_idx); - if (!curr_wqe) { - cmdq_msg_unlock(cmdq); - return -EBUSY; - } - - memset(&wqe, 0, sizeof(wqe)); - - wrapped = cmdq->wrapped; - next_prod_idx = curr_prod_idx + NUM_WQEBBS_FOR_CMDQ_WQE; - if (next_prod_idx >= wq->q_depth) { - cmdq->wrapped = !cmdq->wrapped; - next_prod_idx -= (u16)wq->q_depth; - } - - cmdq_set_lcmd_wqe(&wqe, ASYNC_CMD, buf_in, NULL, wrapped, - mod, cmd, curr_prod_idx); - - cmdq_wqe_fill(curr_wqe, &wqe); - - cmd_info = &cmdq->cmd_infos[curr_prod_idx]; - cmd_info->cmd_type = SPHW_CMD_TYPE_ASYNC; - cmd_info->channel = channel; - /* The caller will not free the cmd_buf of the asynchronous command, - * so there is no need to increase the reference count here - */ - cmd_info->buf_in = buf_in; - - /* LB mode 1 compatible, cmdq 0 also for async, which is sync_no_wait */ - cmdq_set_db(cmdq, SPHW_CMDQ_SYNC, next_prod_idx); - - cmdq_msg_unlock(cmdq); - - return 0; -} - -int cmdq_set_arm_bit(struct sphw_cmdq *cmdq, const void *buf_in, - u16 in_size) -{ - struct sphw_wq *wq = &cmdq->wq; - struct sphw_cmdq_wqe *curr_wqe = NULL, wqe; - u16 curr_prod_idx, next_prod_idx; - int wrapped; - - /* Keep wrapped and doorbell index correct. bh - for tasklet(ceq) */ - spin_lock_bh(&cmdq->cmdq_lock); - - curr_wqe = cmdq_get_wqe(wq, &curr_prod_idx); - if (!curr_wqe) { - spin_unlock_bh(&cmdq->cmdq_lock); - return -EBUSY; - } - - memset(&wqe, 0, sizeof(wqe)); - - wrapped = cmdq->wrapped; - - next_prod_idx = curr_prod_idx + NUM_WQEBBS_FOR_CMDQ_WQE; - if (next_prod_idx >= wq->q_depth) { - cmdq->wrapped = !cmdq->wrapped; - next_prod_idx -= (u16)wq->q_depth; - } - - cmdq_set_inline_wqe(&wqe, SYNC_CMD_DIRECT_RESP, buf_in, in_size, NULL, - wrapped, SPHW_MOD_COMM, CMDQ_SET_ARM_CMD, - curr_prod_idx); - - /* cmdq wqe is not shadow, therefore wqe will be written to wq */ - cmdq_wqe_fill(curr_wqe, &wqe); - - cmdq->cmd_infos[curr_prod_idx].cmd_type = SPHW_CMD_TYPE_SET_ARM; - - cmdq_set_db(cmdq, cmdq->cmdq_type, next_prod_idx); - - spin_unlock_bh(&cmdq->cmdq_lock); - - return 0; -} - -static int cmdq_params_valid(void *hwdev, struct sphw_cmd_buf *buf_in) -{ - if (!buf_in || !hwdev) { - pr_err("Invalid CMDQ buffer addr: %p or hwdev: %p\n", - buf_in, hwdev); - return -EINVAL; - } - - if (!buf_in->size || buf_in->size > SPHW_CMDQ_MAX_DATA_SIZE) { - pr_err("Invalid CMDQ buffer size: 0x%x\n", buf_in->size); - return -EINVAL; - } - - return 0; -} - -#define WAIT_CMDQ_ENABLE_TIMEOUT 300 -static int wait_cmdqs_enable(struct sphw_cmdqs *cmdqs) -{ - unsigned long end; - - end = jiffies + msecs_to_jiffies(WAIT_CMDQ_ENABLE_TIMEOUT); - do { - if (cmdqs->status & SPHW_CMDQ_ENABLE) - return 0; - } while (time_before(jiffies, end) && cmdqs->hwdev->chip_present_flag && - !cmdqs->disable_flag); - - cmdqs->disable_flag = 1; - - return -EBUSY; -} - -int sphw_cmdq_direct_resp(void *hwdev, u8 mod, u8 cmd, struct sphw_cmd_buf *buf_in, - u64 *out_param, u32 timeout, u16 channel) -{ - struct sphw_cmdqs *cmdqs = NULL; - int err = cmdq_params_valid(hwdev, buf_in); - - if (err) { - pr_err("Invalid CMDQ parameters\n"); - return err; - } - - /* to do : support send cmdq only when cmdq init*/ - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) - return -EPERM; - - cmdqs = ((struct sphw_hwdev *)hwdev)->cmdqs; - err = wait_cmdqs_enable(cmdqs); - if (err) { - sdk_err(cmdqs->hwdev->dev_hdl, "Cmdq is disable\n"); - return err; - } - - err = cmdq_sync_cmd_direct_resp(&cmdqs->cmdq[SPHW_CMDQ_SYNC], - mod, cmd, buf_in, out_param, - timeout, channel); - - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) - return -ETIMEDOUT; - else - return err; -} - -int sphw_cmdq_detail_resp(void *hwdev, u8 mod, u8 cmd, struct sphw_cmd_buf *buf_in, - struct sphw_cmd_buf *buf_out, u64 *out_param, u32 timeout, u16 channel) -{ - struct sphw_cmdqs *cmdqs = NULL; - int err = cmdq_params_valid(hwdev, buf_in); - - if (err) - return err; - - cmdqs = ((struct sphw_hwdev *)hwdev)->cmdqs; - - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) /*to do*/ - return -EPERM; - - err = wait_cmdqs_enable(cmdqs); - if (err) { - sdk_err(cmdqs->hwdev->dev_hdl, "Cmdq is disable\n"); - return err; - } - - err = cmdq_sync_cmd_detail_resp(&cmdqs->cmdq[SPHW_CMDQ_SYNC], - mod, cmd, buf_in, buf_out, out_param, - timeout, channel); - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) - return -ETIMEDOUT; - else - return err; -} - -int sphw_cos_id_detail_resp(void *hwdev, u8 mod, u8 cmd, u8 cos_id, struct sphw_cmd_buf *buf_in, - struct sphw_cmd_buf *buf_out, u64 *out_param, u32 timeout, u16 channel) -{ - struct sphw_cmdqs *cmdqs = NULL; - int err = cmdq_params_valid(hwdev, buf_in); - - if (err) - return err; - - cmdqs = ((struct sphw_hwdev *)hwdev)->cmdqs; - - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) /*to do*/ - return -EPERM; - - err = wait_cmdqs_enable(cmdqs); - if (err) { - sdk_err(cmdqs->hwdev->dev_hdl, "Cmdq is disable\n"); - return err; - } - - if (cos_id >= SPHW_MAX_CMDQ_TYPES) { - sdk_err(cmdqs->hwdev->dev_hdl, "Cmdq id is invalid\n"); - return -EINVAL; - } - - err = cmdq_sync_cmd_detail_resp(&cmdqs->cmdq[cos_id], mod, cmd, - buf_in, buf_out, out_param, - timeout, channel); - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) - return -ETIMEDOUT; - else - return err; -} - -int sphw_cmdq_async(void *hwdev, u8 mod, u8 cmd, struct sphw_cmd_buf *buf_in, u16 channel) -{ - struct sphw_cmdqs *cmdqs = NULL; - int err = cmdq_params_valid(hwdev, buf_in); - - if (err) - return err; - - cmdqs = ((struct sphw_hwdev *)hwdev)->cmdqs; - - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) /*to do*/ - return -EPERM; - - err = wait_cmdqs_enable(cmdqs); - if (err) { - sdk_err(cmdqs->hwdev->dev_hdl, "Cmdq is disable\n"); - return err; - } - /* LB mode 1 compatible, cmdq 0 also for async, which is sync_no_wait*/ - return cmdq_async_cmd(&cmdqs->cmdq[SPHW_CMDQ_SYNC], mod, - cmd, buf_in, channel); -} - -int sphw_set_arm_bit(void *hwdev, enum sphw_set_arm_type q_type, u16 q_id) -{ - struct sphw_cmdqs *cmdqs = NULL; - struct sphw_cmdq *cmdq = NULL; - struct sphw_cmdq_arm_bit arm_bit; - enum sphw_cmdq_type cmdq_type = SPHW_CMDQ_SYNC; - u16 in_size; - int err; - - if (!hwdev) - return -EINVAL; - - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag))/* to do*/ - return -EPERM; - - cmdqs = ((struct sphw_hwdev *)hwdev)->cmdqs; - - if (!(cmdqs->status & SPHW_CMDQ_ENABLE)) - return -EBUSY; - - if (q_type == SPHW_SET_ARM_CMDQ) { - if (q_id >= SPHW_MAX_CMDQ_TYPES) - return -EFAULT; - - cmdq_type = q_id; - } - /* sq is using interrupt now, so we only need to set arm bit for cmdq, - * remove comment below if need to set sq arm bit - * else - * cmdq_type = SPHW_CMDQ_SYNC; - */ - - cmdq = &cmdqs->cmdq[cmdq_type]; - - arm_bit.q_type = q_type; - arm_bit.q_id = q_id; - in_size = sizeof(arm_bit); - - err = cmdq_set_arm_bit(cmdq, &arm_bit, in_size); - if (err) { - sdk_err(cmdqs->hwdev->dev_hdl, - "Failed to set arm for q_type: %d, qid %d\n", - q_type, q_id); - return err; - } - - return 0; -} - -static void clear_wqe_complete_bit(struct sphw_cmdq *cmdq, - struct sphw_cmdq_wqe *wqe, u16 ci) -{ - struct sphw_ctrl *ctrl = NULL; - u32 header_info = WQE_HEADER(wqe)->header_info; - enum data_format df = CMDQ_WQE_HEADER_GET(header_info, DATA_FMT); - - if (df == DATA_SGE) - ctrl = &wqe->wqe_lcmd.ctrl; - else - ctrl = &wqe->inline_wqe.wqe_scmd.ctrl; - - /* clear HW busy bit */ - ctrl->ctrl_info = 0; - cmdq->cmd_infos[ci].cmd_type = SPHW_CMD_TYPE_NONE; - - wmb(); /* verify wqe is clear */ - - sphw_wq_put_wqebbs(&cmdq->wq, NUM_WQEBBS_FOR_CMDQ_WQE); -} - -static void cmdq_sync_cmd_handler(struct sphw_cmdq *cmdq, - struct sphw_cmdq_wqe *wqe, u16 ci) -{ - spin_lock(&cmdq->cmdq_lock); - - cmdq_update_cmd_status(cmdq, ci, wqe); - - if (cmdq->cmd_infos[ci].cmpt_code) { - *cmdq->cmd_infos[ci].cmpt_code = CMDQ_COMPLETE_CMPT_CODE; - cmdq->cmd_infos[ci].cmpt_code = NULL; - } - - /* make sure cmpt_code operation before done operation */ - smp_rmb(); - - if (cmdq->cmd_infos[ci].done) { - complete(cmdq->cmd_infos[ci].done); - cmdq->cmd_infos[ci].done = NULL; - } - - spin_unlock(&cmdq->cmdq_lock); - - cmdq_clear_cmd_buf(&cmdq->cmd_infos[ci], cmdq->hwdev); - clear_wqe_complete_bit(cmdq, wqe, ci); -} - -static void cmdq_async_cmd_handler(struct sphw_hwdev *hwdev, - struct sphw_cmdq *cmdq, - struct sphw_cmdq_wqe *wqe, u16 ci) -{ - cmdq_clear_cmd_buf(&cmdq->cmd_infos[ci], hwdev); - clear_wqe_complete_bit(cmdq, wqe, ci); -} - -static int cmdq_arm_ceq_handler(struct sphw_cmdq *cmdq, - struct sphw_cmdq_wqe *wqe, u16 ci) -{ - struct sphw_ctrl *ctrl = &wqe->inline_wqe.wqe_scmd.ctrl; - u32 ctrl_info = ctrl->ctrl_info; - - if (!WQE_COMPLETED(ctrl_info)) - return -EBUSY; - - clear_wqe_complete_bit(cmdq, wqe, ci); - - return 0; -} - -#define SPHW_CMDQ_WQE_HEAD_LEN 32 -static void sphw_dump_cmdq_wqe_head(struct sphw_hwdev *hwdev, struct sphw_cmdq_wqe *wqe) -{ - u32 i; - u32 *data = (u32 *)wqe; - - for (i = 0; i < (SPHW_CMDQ_WQE_HEAD_LEN / sizeof(u32)); i += 4) { - sdk_info(hwdev->dev_hdl, "wqe data: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", - *(data + i), *(data + i + 1), *(data + i + 2), - *(data + i + 3)); - } -} - -void sphw_cmdq_ceq_handler(void *handle, u32 ceqe_data) -{ - struct sphw_cmdqs *cmdqs = ((struct sphw_hwdev *)handle)->cmdqs; - enum sphw_cmdq_type cmdq_type = CEQE_CMDQ_GET(ceqe_data, TYPE); - struct sphw_cmdq *cmdq = &cmdqs->cmdq[cmdq_type]; - struct sphw_hwdev *hwdev = cmdqs->hwdev; - struct sphw_cmdq_wqe *wqe = NULL; - struct sphw_cmdq_wqe_lcmd *wqe_lcmd = NULL; - struct sphw_cmdq_cmd_info *cmd_info = NULL; - u32 ctrl_info; - u16 ci; - - while ((wqe = cmdq_read_wqe(&cmdq->wq, &ci)) != NULL) { - cmd_info = &cmdq->cmd_infos[ci]; - - switch (cmd_info->cmd_type) { - case SPHW_CMD_TYPE_NONE: - return; - case SPHW_CMD_TYPE_TIMEOUT: - sdk_warn(hwdev->dev_hdl, "Cmdq timeout, q_id: %u, ci: %u\n", - cmdq_type, ci); - sphw_dump_cmdq_wqe_head(hwdev, wqe); - fallthrough; - case SPHW_CMD_TYPE_FAKE_TIMEOUT: - cmdq_clear_cmd_buf(cmd_info, hwdev); - clear_wqe_complete_bit(cmdq, wqe, ci); - break; - case SPHW_CMD_TYPE_SET_ARM: - if (cmdq_arm_ceq_handler(cmdq, wqe, ci)) - return; - - break; - default: - /* only arm bit is using scmd wqe, the wqe is lcmd */ - wqe_lcmd = &wqe->wqe_lcmd; - ctrl_info = wqe_lcmd->ctrl.ctrl_info; - - if (!WQE_COMPLETED(ctrl_info)) - return; - - /* For FORCE_STOP cmd_type, we also need to wait for - * the firmware processing to complete to prevent the - * firmware from accessing the released cmd_buf - */ - if (cmd_info->cmd_type == SPHW_CMD_TYPE_FORCE_STOP) { - cmdq_clear_cmd_buf(cmd_info, hwdev); - clear_wqe_complete_bit(cmdq, wqe, ci); - } else if (cmd_info->cmd_type == SPHW_CMD_TYPE_ASYNC) { - cmdq_async_cmd_handler(hwdev, cmdq, wqe, ci); - } else { - cmdq_sync_cmd_handler(cmdq, wqe, ci); - } - - break; - } - } -} - -static void cmdq_init_queue_ctxt(struct sphw_cmdqs *cmdqs, - struct sphw_cmdq *cmdq, - struct cmdq_ctxt_info *ctxt_info) -{ - struct sphw_wq *wq = &cmdq->wq; - u64 cmdq_first_block_paddr, pfn; - u16 start_ci = (u16)wq->cons_idx; - - pfn = CMDQ_PFN(sphw_wq_get_first_wqe_page_addr(wq)); - - ctxt_info->curr_wqe_page_pfn = - CMDQ_CTXT_PAGE_INFO_SET(1, HW_BUSY_BIT) | - CMDQ_CTXT_PAGE_INFO_SET(1, CEQ_EN) | - CMDQ_CTXT_PAGE_INFO_SET(1, CEQ_ARM) | - CMDQ_CTXT_PAGE_INFO_SET(SPHW_CEQ_ID_CMDQ, EQ_ID) | - CMDQ_CTXT_PAGE_INFO_SET(pfn, CURR_WQE_PAGE_PFN); - - if (!WQ_IS_0_LEVEL_CLA(wq)) { - cmdq_first_block_paddr = cmdqs->wq_block_paddr; - pfn = CMDQ_PFN(cmdq_first_block_paddr); - } - - ctxt_info->wq_block_pfn = CMDQ_CTXT_BLOCK_INFO_SET(start_ci, CI) | - CMDQ_CTXT_BLOCK_INFO_SET(pfn, WQ_BLOCK_PFN); -} - -static int init_cmdq(struct sphw_cmdq *cmdq, struct sphw_hwdev *hwdev, - enum sphw_cmdq_type q_type) -{ - void __iomem *db_base; - int err; - - cmdq->cmdq_type = q_type; - cmdq->wrapped = 1; - cmdq->hwdev = hwdev; - - spin_lock_init(&cmdq->cmdq_lock); - - cmdq->cmd_infos = kcalloc(cmdq->wq.q_depth, sizeof(*cmdq->cmd_infos), - GFP_KERNEL); - if (!cmdq->cmd_infos) { - sdk_err(hwdev->dev_hdl, "Failed to allocate cmdq infos\n"); - err = -ENOMEM; - goto cmd_infos_err; - } - - err = sphw_alloc_db_addr(hwdev, &db_base, NULL); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to allocate doorbell address\n"); - goto alloc_db_err; - } - - cmdq->db_base = (u8 *)db_base; - return 0; - -alloc_db_err: - kfree(cmdq->cmd_infos); - -cmd_infos_err: - - return err; -} - -static void free_cmdq(struct sphw_hwdev *hwdev, struct sphw_cmdq *cmdq) -{ - sphw_free_db_addr(hwdev, cmdq->db_base, NULL); - kfree(cmdq->cmd_infos); -} - -static int sphw_set_cmdq_ctxts(struct sphw_hwdev *hwdev) -{ - struct sphw_cmdqs *cmdqs = hwdev->cmdqs; - enum sphw_cmdq_type cmdq_type; - int err; - - cmdq_type = SPHW_CMDQ_SYNC; - for (; cmdq_type < SPHW_MAX_CMDQ_TYPES; cmdq_type++) { - err = sphw_set_cmdq_ctxt(hwdev, (u8)cmdq_type, &cmdqs->cmdq[cmdq_type].cmdq_ctxt); - if (err) - return err; - } - - cmdqs->status |= SPHW_CMDQ_ENABLE; - cmdqs->disable_flag = 0; - - return 0; -} - -static void cmdq_flush_sync_cmd(struct sphw_cmdq_cmd_info *cmd_info) -{ - if (cmd_info->cmd_type != SPHW_CMD_TYPE_DIRECT_RESP && - cmd_info->cmd_type != SPHW_CMD_TYPE_SGE_RESP) - return; - - cmd_info->cmd_type = SPHW_CMD_TYPE_FORCE_STOP; - - if (cmd_info->cmpt_code && - *cmd_info->cmpt_code == CMDQ_SEND_CMPT_CODE) - *cmd_info->cmpt_code = CMDQ_FORCE_STOP_CMPT_CODE; - - if (cmd_info->done) { - complete(cmd_info->done); - cmd_info->done = NULL; - cmd_info->cmpt_code = NULL; - cmd_info->direct_resp = NULL; - cmd_info->errcode = NULL; - } -} - -void sphw_cmdq_flush_cmd(struct sphw_hwdev *hwdev, struct sphw_cmdq *cmdq) -{ - struct sphw_cmdq_cmd_info *cmd_info = NULL; - u16 ci = 0; - - spin_lock_bh(&cmdq->cmdq_lock); - - while (cmdq_read_wqe(&cmdq->wq, &ci)) { - sphw_wq_put_wqebbs(&cmdq->wq, NUM_WQEBBS_FOR_CMDQ_WQE); - cmd_info = &cmdq->cmd_infos[ci]; - - if (cmd_info->cmd_type == SPHW_CMD_TYPE_DIRECT_RESP || - cmd_info->cmd_type == SPHW_CMD_TYPE_SGE_RESP) - cmdq_flush_sync_cmd(cmd_info); - } - - spin_unlock_bh(&cmdq->cmdq_lock); -} - -void sphw_cmdq_flush_channel_sync_cmd(struct sphw_hwdev *hwdev, u16 channel) -{ - struct sphw_cmdq_cmd_info *cmd_info = NULL; - struct sphw_cmdq *cmdq = NULL; - struct sphw_wq *wq = NULL; - u16 wqe_cnt, ci, i; - - if (channel >= SPHW_CHANNEL_MAX) - return; - - cmdq = &hwdev->cmdqs->cmdq[SPHW_CMDQ_SYNC]; - - spin_lock_bh(&cmdq->cmdq_lock); - - wq = &cmdq->wq; - ci = wq->cons_idx; - wqe_cnt = (u16)WQ_MASK_IDX(wq, wq->prod_idx + - wq->q_depth - wq->cons_idx); - for (i = 0; i < wqe_cnt; i++) { - cmd_info = &cmdq->cmd_infos[WQ_MASK_IDX(wq, ci + i)]; - - if (cmd_info->channel == channel) - cmdq_flush_sync_cmd(cmd_info); - } - - spin_unlock_bh(&cmdq->cmdq_lock); -} - -static void cmdq_reset_all_cmd_buff(struct sphw_cmdq *cmdq) -{ - u16 i; - - for (i = 0; i < cmdq->wq.q_depth; i++) - cmdq_clear_cmd_buf(&cmdq->cmd_infos[i], cmdq->hwdev); -} - -int sphw_cmdq_set_channel_status(struct sphw_hwdev *hwdev, u16 channel, bool enable) -{ - if (channel >= SPHW_CHANNEL_MAX) - return -EINVAL; - - if (enable) { - clear_bit(channel, &hwdev->cmdqs->channel_stop); - } else { - set_bit(channel, &hwdev->cmdqs->channel_stop); - sphw_cmdq_flush_channel_sync_cmd(hwdev, channel); - } - - sdk_info(hwdev->dev_hdl, "%s cmdq channel 0x%x\n", - enable ? "Enable" : "Disable", channel); - - return 0; -} - -void sphw_cmdq_enable_channel_lock(struct sphw_hwdev *hwdev, bool enable) -{ - hwdev->cmdqs->lock_channel_en = enable; - - sdk_info(hwdev->dev_hdl, "%s cmdq channel lock\n", - enable ? "Enable" : "Disable"); -} - -int sphw_reinit_cmdq_ctxts(struct sphw_hwdev *hwdev) -{ - struct sphw_cmdqs *cmdqs = hwdev->cmdqs; - enum sphw_cmdq_type cmdq_type; - - cmdq_type = SPHW_CMDQ_SYNC; - for (; cmdq_type < SPHW_MAX_CMDQ_TYPES; cmdq_type++) { - sphw_cmdq_flush_cmd(hwdev, &cmdqs->cmdq[cmdq_type]); - cmdq_reset_all_cmd_buff(&cmdqs->cmdq[cmdq_type]); - cmdqs->cmdq[cmdq_type].wrapped = 1; - sphw_wq_reset(&cmdqs->cmdq[cmdq_type].wq); - } - - return sphw_set_cmdq_ctxts(hwdev); -} - -static int create_cmdq_wq(struct sphw_cmdqs *cmdqs) -{ - enum sphw_cmdq_type type, cmdq_type; - int err; - - cmdq_type = SPHW_CMDQ_SYNC; - for (; cmdq_type < SPHW_MAX_CMDQ_TYPES; cmdq_type++) { - err = sphw_wq_create(cmdqs->hwdev, &cmdqs->cmdq[cmdq_type].wq, SPHW_CMDQ_DEPTH, - CMDQ_WQEBB_SIZE); - if (err) { - sdk_err(cmdqs->hwdev->dev_hdl, "Failed to create cmdq wq\n"); - goto destroy_wq; - } - } - - /* 1-level CLA must put all cmdq's wq page addr in one wq block */ - if (!WQ_IS_0_LEVEL_CLA(&cmdqs->cmdq[SPHW_CMDQ_SYNC].wq)) { - /* cmdq wq's CLA table is up to 512B */ -#define CMDQ_WQ_CLA_SIZE 512 - if (cmdqs->cmdq[SPHW_CMDQ_SYNC].wq.num_wq_pages > - CMDQ_WQ_CLA_SIZE / sizeof(u64)) { - sdk_err(cmdqs->hwdev->dev_hdl, "Cmdq wq page exceed limit: %lu\n", - CMDQ_WQ_CLA_SIZE / sizeof(u64)); - goto destroy_wq; - } - - cmdqs->wq_block_vaddr = - dma_alloc_coherent(cmdqs->hwdev->dev_hdl, PAGE_SIZE, - &cmdqs->wq_block_paddr, GFP_KERNEL); - if (!cmdqs->wq_block_vaddr) { - sdk_err(cmdqs->hwdev->dev_hdl, "Failed to alloc cmdq wq block\n"); - goto destroy_wq; - } - - type = SPHW_CMDQ_SYNC; - for (; type < SPHW_MAX_CMDQ_TYPES; type++) - memcpy((u8 *)cmdqs->wq_block_vaddr + - CMDQ_WQ_CLA_SIZE * type, - cmdqs->cmdq[type].wq.wq_block_vaddr, - cmdqs->cmdq[type].wq.num_wq_pages * sizeof(u64)); - } - - return 0; - -destroy_wq: - type = SPHW_CMDQ_SYNC; - for (; type < cmdq_type; type++) - sphw_wq_destroy(&cmdqs->cmdq[type].wq); - - return err; -} - -static void destroy_cmdq_wq(struct sphw_cmdqs *cmdqs) -{ - enum sphw_cmdq_type cmdq_type; - - if (cmdqs->wq_block_vaddr) - dma_free_coherent(cmdqs->hwdev->dev_hdl, PAGE_SIZE, - cmdqs->wq_block_vaddr, cmdqs->wq_block_paddr); - - cmdq_type = SPHW_CMDQ_SYNC; - for (; cmdq_type < SPHW_MAX_CMDQ_TYPES; cmdq_type++) - sphw_wq_destroy(&cmdqs->cmdq[cmdq_type].wq); -} - -int sphw_cmdqs_init(struct sphw_hwdev *hwdev) -{ - struct sphw_cmdqs *cmdqs = NULL; - enum sphw_cmdq_type type, cmdq_type; - int err; - - cmdqs = kzalloc(sizeof(*cmdqs), GFP_KERNEL); - if (!cmdqs) - return -ENOMEM; - - hwdev->cmdqs = cmdqs; - cmdqs->hwdev = hwdev; - - cmdqs->cmd_buf_pool = dma_pool_create("sphw_cmdq", hwdev->dev_hdl, - SPHW_CMDQ_BUF_SIZE, - SPHW_CMDQ_BUF_SIZE, 0ULL); - if (!cmdqs->cmd_buf_pool) { - sdk_err(hwdev->dev_hdl, "Failed to create cmdq buffer pool\n"); - err = -ENOMEM; - goto pool_create_err; - } - - err = create_cmdq_wq(cmdqs); - if (err) - goto create_wq_err; - - cmdq_type = SPHW_CMDQ_SYNC; - for (; cmdq_type < SPHW_MAX_CMDQ_TYPES; cmdq_type++) { - err = init_cmdq(&cmdqs->cmdq[cmdq_type], hwdev, cmdq_type); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to initialize cmdq type :%d\n", - cmdq_type); - goto init_cmdq_err; - } - - cmdq_init_queue_ctxt(cmdqs, &cmdqs->cmdq[cmdq_type], - &cmdqs->cmdq[cmdq_type].cmdq_ctxt); - } - - err = sphw_set_cmdq_ctxts(hwdev); - if (err) - goto init_cmdq_err; - - return 0; - -init_cmdq_err: - type = SPHW_CMDQ_SYNC; - for (; type < cmdq_type; type++) - free_cmdq(hwdev, &cmdqs->cmdq[type]); - - destroy_cmdq_wq(cmdqs); - -create_wq_err: - dma_pool_destroy(cmdqs->cmd_buf_pool); - -pool_create_err: - kfree(cmdqs); - - return err; -} - -void sphw_cmdqs_free(struct sphw_hwdev *hwdev) -{ - struct sphw_cmdqs *cmdqs = hwdev->cmdqs; - enum sphw_cmdq_type cmdq_type = SPHW_CMDQ_SYNC; - - cmdqs->status &= ~SPHW_CMDQ_ENABLE; - - for (; cmdq_type < SPHW_MAX_CMDQ_TYPES; cmdq_type++) { - sphw_cmdq_flush_cmd(hwdev, &cmdqs->cmdq[cmdq_type]); - cmdq_reset_all_cmd_buff(&cmdqs->cmdq[cmdq_type]); - free_cmdq(cmdqs->hwdev, &cmdqs->cmdq[cmdq_type]); - } - - destroy_cmdq_wq(cmdqs); - - dma_pool_destroy(cmdqs->cmd_buf_pool); - - kfree(cmdqs); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cmdq.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cmdq.h deleted file mode 100644 index 2c1f1bbda4ad..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cmdq.h +++ /dev/null @@ -1,195 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_CMDQ_H -#define SPHW_CMDQ_H - -#include "sphw_comm_msg_intf.h" - -#define SPHW_SCMD_DATA_LEN 16 - -#define SPHW_CMDQ_DEPTH 4096 - -enum sphw_cmdq_type { - SPHW_CMDQ_SYNC, - SPHW_CMDQ_ASYNC, - SPHW_MAX_CMDQ_TYPES, -}; - -enum sphw_db_src_type { - SPHW_DB_SRC_CMDQ_TYPE, - SPHW_DB_SRC_L2NIC_SQ_TYPE, -}; - -enum sphw_cmdq_db_type { - SPHW_DB_SQ_RQ_TYPE, - SPHW_DB_CMDQ_TYPE, -}; - -/*hardware define: cmdq wqe*/ -struct sphw_cmdq_header { - u32 header_info; - u32 saved_data; -}; - -struct sphw_scmd_bufdesc { - u32 buf_len; - u32 rsvd; - u8 data[SPHW_SCMD_DATA_LEN]; -}; - -struct sphw_lcmd_bufdesc { - struct sphw_sge sge; - u32 rsvd1; - u64 saved_async_buf; - u64 rsvd3; -}; - -struct sphw_cmdq_db { - u32 db_head; - u32 db_info; -}; - -struct sphw_status { - u32 status_info; -}; - -struct sphw_ctrl { - u32 ctrl_info; -}; - -struct sphw_sge_resp { - struct sphw_sge sge; - u32 rsvd; -}; - -struct sphw_cmdq_completion { - union { - struct sphw_sge_resp sge_resp; - u64 direct_resp; - }; -}; - -struct sphw_cmdq_wqe_scmd { - struct sphw_cmdq_header header; - u64 rsvd; - struct sphw_status status; - struct sphw_ctrl ctrl; - struct sphw_cmdq_completion completion; - struct sphw_scmd_bufdesc buf_desc; -}; - -struct sphw_cmdq_wqe_lcmd { - struct sphw_cmdq_header header; - struct sphw_status status; - struct sphw_ctrl ctrl; - struct sphw_cmdq_completion completion; - struct sphw_lcmd_bufdesc buf_desc; -}; - -struct sphw_cmdq_inline_wqe { - struct sphw_cmdq_wqe_scmd wqe_scmd; -}; - -struct sphw_cmdq_wqe { - union { - struct sphw_cmdq_inline_wqe inline_wqe; - struct sphw_cmdq_wqe_lcmd wqe_lcmd; - }; -}; - -struct sphw_cmdq_arm_bit { - u32 q_type; - u32 q_id; -}; - -enum sphw_cmdq_status { - SPHW_CMDQ_ENABLE = BIT(0), -}; - -enum sphw_cmdq_cmd_type { - SPHW_CMD_TYPE_NONE, - SPHW_CMD_TYPE_SET_ARM, - SPHW_CMD_TYPE_DIRECT_RESP, - SPHW_CMD_TYPE_SGE_RESP, - SPHW_CMD_TYPE_ASYNC, - SPHW_CMD_TYPE_FAKE_TIMEOUT, - SPHW_CMD_TYPE_TIMEOUT, - SPHW_CMD_TYPE_FORCE_STOP, -}; - -struct sphw_cmdq_cmd_info { - enum sphw_cmdq_cmd_type cmd_type; - u16 channel; - - struct completion *done; - int *errcode; - int *cmpt_code; - u64 *direct_resp; - u64 cmdq_msg_id; - - struct sphw_cmd_buf *buf_in; - struct sphw_cmd_buf *buf_out; -}; - -struct sphw_cmdq { - struct sphw_wq wq; - - enum sphw_cmdq_type cmdq_type; - int wrapped; - - /* spinlock for send cmdq commands */ - spinlock_t cmdq_lock; - - /* doorbell area */ - u8 __iomem *db_base; - - struct cmdq_ctxt_info cmdq_ctxt; - - struct sphw_cmdq_cmd_info *cmd_infos; - - struct sphw_hwdev *hwdev; -}; - -struct sphw_cmdqs { - struct sphw_hwdev *hwdev; - - struct pci_pool *cmd_buf_pool; - - /* All cmdq's CLA of a VF occupy a PAGE when cmdq wq is 1-level CLA */ - dma_addr_t wq_block_paddr; - void *wq_block_vaddr; - struct sphw_cmdq cmdq[SPHW_MAX_CMDQ_TYPES]; - - u32 status; - u32 disable_flag; - - bool lock_channel_en; - unsigned long channel_stop; -}; - -enum sphw_set_arm_type { - SPHW_SET_ARM_CMDQ, - SPHW_SET_ARM_SQ, - SPHW_SET_ARM_TYPE_NUM, -}; - -int sphw_set_arm_bit(void *hwdev, enum sphw_set_arm_type q_type, u16 q_id); - -void sphw_cmdq_ceq_handler(void *hwdev, u32 ceqe_data); - -int sphw_reinit_cmdq_ctxts(struct sphw_hwdev *hwdev); - -bool sphw_cmdq_idle(struct sphw_cmdq *cmdq); - -int sphw_cmdqs_init(struct sphw_hwdev *hwdev); - -void sphw_cmdqs_free(struct sphw_hwdev *hwdev); - -void sphw_cmdq_flush_cmd(struct sphw_hwdev *hwdev, struct sphw_cmdq *cmdq); - -int sphw_cmdq_set_channel_status(struct sphw_hwdev *hwdev, u16 channel, bool enable); - -void sphw_cmdq_enable_channel_lock(struct sphw_hwdev *hwdev, bool enable); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_comm_cmd.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_comm_cmd.h deleted file mode 100644 index d0e4c87942b5..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_comm_cmd.h +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_COMMON_CMD_H -#define SPHW_COMMON_CMD_H - -/* COMM Commands between Driver to MPU */ -enum sphw_mgmt_cmd { - COMM_MGMT_CMD_FUNC_RESET = 0, - COMM_MGMT_CMD_FEATURE_NEGO, - COMM_MGMT_CMD_FLUSH_DOORBELL, - COMM_MGMT_CMD_START_FLUSH, - COMM_MGMT_CMD_SET_FUNC_FLR, - COMM_MGMT_CMD_GET_GLOBAL_ATTR, - - COMM_MGMT_CMD_SET_CMDQ_CTXT = 20, - COMM_MGMT_CMD_SET_VAT, - COMM_MGMT_CMD_CFG_PAGESIZE, - COMM_MGMT_CMD_CFG_MSIX_CTRL_REG, - COMM_MGMT_CMD_SET_CEQ_CTRL_REG, - COMM_MGMT_CMD_SET_DMA_ATTR, - - COMM_MGMT_CMD_GET_MQM_FIX_INFO = 40, - COMM_MGMT_CMD_SET_MQM_CFG_INFO, - COMM_MGMT_CMD_SET_MQM_SRCH_GPA, - COMM_MGMT_CMD_SET_PPF_TMR, - COMM_MGMT_CMD_SET_PPF_HT_GPA, - COMM_MGMT_CMD_SET_FUNC_TMR_BITMAT, - - COMM_MGMT_CMD_GET_FW_VERSION = 60, - COMM_MGMT_CMD_GET_BOARD_INFO, - COMM_MGMT_CMD_SYNC_TIME, - COMM_MGMT_CMD_GET_HW_PF_INFOS, - COMM_MGMT_CMD_SEND_BDF_INFO, - COMM_MGMT_CMD_GET_VIRTIO_BDF_INFO, - - COMM_MGMT_CMD_UPDATE_FW = 80, - COMM_MGMT_CMD_ACTIVE_FW, - COMM_MGMT_CMD_HOT_ACTIVE_FW, - COMM_MGMT_CMD_HOT_ACTIVE_DONE_NOTICE, - COMM_MGMT_CMD_SWITCH_CFG, - COMM_MGMT_CMD_CHECK_FLASH, - COMM_MGMT_CMD_CHECK_FLASH_RW, - COMM_MGMT_CMD_RESOURCE_CFG, - - COMM_MGMT_CMD_FAULT_REPORT = 100, - COMM_MGMT_CMD_WATCHDOG_INFO, - COMM_MGMT_CMD_MGMT_RESET, - COMM_MGMT_CMD_FFM_SET, - - COMM_MGMT_CMD_GET_LOG = 120, - COMM_MGMT_CMD_TEMP_OP, - COMM_MGMT_CMD_EN_AUTO_RST_CHIP, - COMM_MGMT_CMD_CFG_REG, - COMM_MGMT_CMD_GET_CHIP_ID, - COMM_MGMT_CMD_SYSINFO_DFX, - COMM_MGMT_CMD_PCIE_DFX_NTC, -}; - -#endif /* SPHW_COMMON_CMD_H */ diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_comm_msg_intf.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_comm_msg_intf.h deleted file mode 100644 index fd12a47e5bb5..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_comm_msg_intf.h +++ /dev/null @@ -1,273 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_COMM_MSG_INTF_H -#define SPHW_COMM_MSG_INTF_H - -#include "sphw_mgmt_msg_base.h" - -#define FUNC_RESET_FLAG_MAX_VALUE ((1U << (RES_TYPE_IPSEC + 1)) - 1) -struct comm_cmd_func_reset { - struct mgmt_msg_head head; - - u16 func_id; - u16 rsvd1[3]; - u64 reset_flag; -}; - -enum { - COMM_F_API_CHAIN = 1U << 0, -}; - -#define COMM_MAX_FEATURE_QWORD 4 -struct comm_cmd_feature_nego { - struct mgmt_msg_head head; - - u16 func_id; - u8 opcode; /* 1: set, 0: get */ - u8 rsvd; - u64 s_feature[COMM_MAX_FEATURE_QWORD]; -}; - -struct comm_cmd_clear_doorbell { - struct mgmt_msg_head head; - - u16 func_id; - u16 rsvd1[3]; -}; - -struct comm_cmd_clear_resource { - struct mgmt_msg_head head; - - u16 func_id; - u16 rsvd1[3]; -}; - -struct comm_global_attr { - u8 max_host_num; - u8 max_pf_num; - u16 vf_id_start; - - u8 mgmt_host_node_id; /* for api cmd to mgmt cpu */ - u8 rsvd1[3]; - - u32 rsvd2[8]; -}; - -struct comm_cmd_get_glb_attr { - struct mgmt_msg_head head; - - struct comm_global_attr attr; -}; - -enum sphw_fw_ver_type { - SPHW_FW_VER_TYPE_BOOT, - SPHW_FW_VER_TYPE_MPU, - SPHW_FW_VER_TYPE_NPU, - SPHW_FW_VER_TYPE_SMU, - SPHW_FW_VER_TYPE_CFG, -}; - -#define SPHW_FW_VERSION_LEN 16 -#define SPHW_FW_COMPILE_TIME_LEN 20 -struct comm_cmd_get_fw_version { - struct mgmt_msg_head head; - - u16 fw_type; - u16 rsvd1; - u8 ver[SPHW_FW_VERSION_LEN]; - u8 time[SPHW_FW_COMPILE_TIME_LEN]; -}; - -/* hardware define: cmdq context */ -struct cmdq_ctxt_info { - u64 curr_wqe_page_pfn; - u64 wq_block_pfn; -}; - -struct comm_cmd_cmdq_ctxt { - struct mgmt_msg_head head; - - u16 func_id; - u8 cmdq_id; - u8 rsvd1[5]; - - struct cmdq_ctxt_info ctxt; -}; - -struct comm_cmd_root_ctxt { - struct mgmt_msg_head head; - - u16 func_id; - u8 set_cmdq_depth; - u8 cmdq_depth; - u16 rx_buf_sz; - u8 lro_en; - u8 rsvd1; - u16 sq_depth; - u16 rq_depth; - u64 rsvd2; -}; - -struct comm_cmd_wq_page_size { - struct mgmt_msg_head head; - - u16 func_id; - u8 opcode; - /* real_size=4KB*2^page_size, range(0~20) must be checked by driver */ - u8 page_size; - - u32 rsvd1; -}; - -struct comm_cmd_msix_config { - struct mgmt_msg_head head; - - u16 func_id; - u8 opcode; - u8 rsvd1; - u16 msix_index; - u8 pending_cnt; - u8 coalesce_timer_cnt; - u8 resend_timer_cnt; - u8 lli_timer_cnt; - u8 lli_credit_cnt; - u8 rsvd2[5]; -}; - -struct comm_cmd_dma_attr_config { - struct mgmt_msg_head head; - - u16 func_id; - u8 entry_idx; - u8 st; - u8 at; - u8 ph; - u8 no_snooping; - u8 tph_en; - u32 resv1; -}; - -struct comm_cmd_ceq_ctrl_reg { - struct mgmt_msg_head head; - - u16 func_id; - u16 q_id; - u32 ctrl0; - u32 ctrl1; - u32 rsvd1; -}; - -struct comm_cmd_func_tmr_bitmap_op { - struct mgmt_msg_head head; - - u16 func_id; - u8 opcode; /* 1: start, 0: stop */ - u8 rsvd1[5]; -}; - -struct comm_cmd_ppf_tmr_op { - struct mgmt_msg_head head; - - u8 ppf_id; - u8 opcode; /* 1: start, 0: stop */ - u8 rsvd1[6]; -}; - -struct comm_cmd_ht_gpa { - struct mgmt_msg_head head; - - u8 host_id; - u32 rsvd1[7]; - u64 page_pa0; - u64 page_pa1; -}; - -struct comm_cmd_get_eqm_num { - struct mgmt_msg_head head; - - u8 host_id; - u8 rsvd1[3]; - u32 chunk_num; - u32 search_gpa_num; -}; - -struct comm_cmd_eqm_cfg { - struct mgmt_msg_head head; - - u8 host_id; - u8 valid; - u16 rsvd1; - u32 page_size; - u32 rsvd2; -}; - -struct comm_cmd_eqm_search_gpa { - struct mgmt_msg_head head; - - u8 host_id; - u8 rsvd1[3]; - u32 start_idx; - u32 num; - u32 rsvd2; - u64 gpa_hi52[0]; -}; - -struct comm_cmd_ffm_info { - struct mgmt_msg_head head; - - u8 node_id; - /* error level of the interrupt source */ - u8 err_level; - /* Classification by interrupt source properties */ - u16 err_type; - u32 err_csr_addr; - u32 err_csr_value; - u32 rsvd1; -}; - -struct sphw_board_info { - u8 board_type; - u8 port_num; - u8 port_speed; - u8 pcie_width; - u8 host_num; - u8 pf_num; - u16 vf_total_num; - u8 tile_num; - u8 qcm_num; - u8 core_num; - u8 work_mode; - u8 service_mode; - u8 pcie_mode; - u8 boot_sel; - u8 board_id; - u32 cfg_addr; -}; - -struct comm_cmd_board_info { - struct mgmt_msg_head head; - - struct sphw_board_info info; - u32 rsvd[25]; -}; - -struct comm_cmd_sync_time { - struct mgmt_msg_head head; - - u64 mstime; - u64 rsvd1; -}; - -struct comm_cmd_bdf_info { - struct mgmt_msg_head head; - - u16 function_idx; - u8 rsvd1[2]; - u8 bus; - u8 device; - u8 function; - u8 rsvd2[5]; -}; - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_common.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_common.c deleted file mode 100644 index aaba9e68ba31..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_common.c +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include <linux/kernel.h> -#include <linux/dma-mapping.h> -#include <linux/delay.h> - -#include "sphw_common.h" - -int sphw_dma_alloc_coherent_align(void *dev_hdl, u64 size, u64 align, unsigned int flag, - struct sphw_dma_addr_align *mem_align) -{ - void *vaddr = NULL, *align_vaddr = NULL; - dma_addr_t paddr, align_paddr; - u64 real_size = size; - - vaddr = dma_alloc_coherent(dev_hdl, real_size, &paddr, flag); - if (!vaddr) - return -ENOMEM; - - align_paddr = ALIGN(paddr, align); - /* align */ - if (align_paddr == paddr) { - align_vaddr = vaddr; - goto out; - } - - dma_free_coherent(dev_hdl, real_size, vaddr, paddr); - - /* realloc memory for align */ - real_size = size + align; - vaddr = dma_alloc_coherent(dev_hdl, real_size, &paddr, flag); - if (!vaddr) - return -ENOMEM; - - align_paddr = ALIGN(paddr, align); - align_vaddr = (void *)((u64)vaddr + (align_paddr - paddr)); - -out: - mem_align->real_size = (u32)real_size; - mem_align->ori_vaddr = vaddr; - mem_align->ori_paddr = paddr; - mem_align->align_vaddr = align_vaddr; - mem_align->align_paddr = align_paddr; - - return 0; -} - -void sphw_dma_free_coherent_align(void *dev_hdl, struct sphw_dma_addr_align *mem_align) -{ - dma_free_coherent(dev_hdl, mem_align->real_size, - mem_align->ori_vaddr, mem_align->ori_paddr); -} - -int sphw_wait_for_timeout(void *priv_data, wait_cpl_handler handler, - u32 wait_total_ms, u32 wait_once_us) -{ - enum sphw_wait_return ret; - unsigned long end; - /* Take 9/10 * wait_once_us as the minimum sleep time of usleep_range */ - u32 usleep_min = wait_once_us - wait_once_us / 10; - - if (!handler) - return -EINVAL; - - end = jiffies + msecs_to_jiffies(wait_total_ms); - do { - ret = handler(priv_data); - if (ret == WAIT_PROCESS_CPL) - return 0; - else if (ret == WAIT_PROCESS_ERR) - return -EIO; - - /* Sleep more than 20ms using msleep is accurate */ - if (wait_once_us >= 20 * USEC_PER_MSEC) - msleep(wait_once_us / USEC_PER_MSEC); - else - usleep_range(usleep_min, wait_once_us); - } while (time_before(jiffies, end)); - - ret = handler(priv_data); - if (ret == WAIT_PROCESS_CPL) - return 0; - else if (ret == WAIT_PROCESS_ERR) - return -EIO; - - return -ETIMEDOUT; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_common.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_common.h deleted file mode 100644 index 05327bd4bcfe..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_common.h +++ /dev/null @@ -1,106 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_COMMON_H -#define SPHW_COMMON_H - -#include <linux/types.h> - -struct sphw_dma_addr_align { - u32 real_size; - - void *ori_vaddr; - dma_addr_t ori_paddr; - - void *align_vaddr; - dma_addr_t align_paddr; -}; - -int sphw_dma_alloc_coherent_align(void *dev_hdl, u64 size, u64 align, unsigned int flag, - struct sphw_dma_addr_align *mem_align); - -void sphw_dma_free_coherent_align(void *dev_hdl, struct sphw_dma_addr_align *mem_align); - -enum sphw_wait_return { - WAIT_PROCESS_CPL = 0, - WAIT_PROCESS_WAITING = 1, - WAIT_PROCESS_ERR = 2, -}; - -typedef enum sphw_wait_return (*wait_cpl_handler)(void *priv_data); - -int sphw_wait_for_timeout(void *priv_data, wait_cpl_handler handler, - u32 wait_total_ms, u32 wait_once_us); - -/* * - * sphw_cpu_to_be32 - convert data to big endian 32 bit format - * @data: the data to convert - * @len: length of data to convert, must be Multiple of 4B - */ -static inline void sphw_cpu_to_be32(void *data, int len) -{ - int i, chunk_sz = sizeof(u32); - u32 *mem = data; - - if (!data) - return; - - len = len / chunk_sz; - - for (i = 0; i < len; i++) { - *mem = cpu_to_be32(*mem); - mem++; - } -} - -/* * - * sphw_cpu_to_be32 - convert data from big endian 32 bit format - * @data: the data to convert - * @len: length of data to convert - */ -static inline void sphw_be32_to_cpu(void *data, int len) -{ - int i, chunk_sz = sizeof(u32); - u32 *mem = data; - - if (!data) - return; - - len = len / chunk_sz; - - for (i = 0; i < len; i++) { - *mem = be32_to_cpu(*mem); - mem++; - } -} - -struct sphw_sge { - u32 hi_addr; - u32 lo_addr; - u32 len; -}; - -/* * - * sphw_set_sge - set dma area in scatter gather entry - * @sge: scatter gather entry - * @addr: dma address - * @len: length of relevant data in the dma address - */ -static inline void sphw_set_sge(struct sphw_sge *sge, dma_addr_t addr, int len) -{ - sge->hi_addr = upper_32_bits(addr); - sge->lo_addr = lower_32_bits(addr); - sge->len = len; -} - -#define sdk_err(dev, format, ...) dev_err(dev, "[COMM]" format, ##__VA_ARGS__) -#define sdk_warn(dev, format, ...) dev_warn(dev, "[COMM]" format, ##__VA_ARGS__) -#define sdk_notice(dev, format, ...) dev_notice(dev, "[COMM]" format, ##__VA_ARGS__) -#define sdk_info(dev, format, ...) dev_info(dev, "[COMM]" format, ##__VA_ARGS__) - -#define nic_err(dev, format, ...) dev_err(dev, "[NIC]" format, ##__VA_ARGS__) -#define nic_warn(dev, format, ...) dev_warn(dev, "[NIC]" format, ##__VA_ARGS__) -#define nic_notice(dev, format, ...) dev_notice(dev, "[NIC]" format, ##__VA_ARGS__) -#define nic_info(dev, format, ...) dev_info(dev, "[NIC]" format, ##__VA_ARGS__) - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_crm.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_crm.h deleted file mode 100644 index 8cce36698e3d..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_crm.h +++ /dev/null @@ -1,982 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_CRM_H -#define SPHW_CRM_H - -#define ARRAY_LEN(arr) ((int)((int)sizeof(arr) / (int)sizeof((arr)[0]))) - -#define SPHW_MGMT_VERSION_MAX_LEN 32 - -#define SPHW_FW_VERSION_NAME 16 -#define SPHW_FW_VERSION_SECTION_CNT 4 -#define SPHW_FW_VERSION_SECTION_BORDER 0xFF -struct sphw_fw_version { - u8 mgmt_ver[SPHW_FW_VERSION_NAME]; - u8 microcode_ver[SPHW_FW_VERSION_NAME]; - u8 boot_ver[SPHW_FW_VERSION_NAME]; -}; - -#define SPHW_MGMT_CMD_UNSUPPORTED 0xFF - -/* show each drivers only such as nic_service_cap, - * toe_service_cap structure, but not show service_cap - */ -enum sphw_service_type { - SERVICE_T_NIC = 0, - SERVICE_T_OVS, - SERVICE_T_ROCE, - SERVICE_T_TOE, - SERVICE_T_IOE, - SERVICE_T_FC, - SERVICE_T_VBS, - SERVICE_T_IPSEC, - SERVICE_T_VIRTIO, - SERVICE_T_MIGRATE, - SERVICE_T_MAX, - - /* Only used for interruption resource management, - * mark the request module - */ - SERVICE_T_INTF = (1 << 15), - SERVICE_T_CQM = (1 << 16), -}; - -struct nic_service_cap { - u16 max_sqs; - u16 max_rqs; -}; - -/* PF/VF ToE service resource structure */ -struct dev_toe_svc_cap { - /* PF resources */ - u32 max_pctxs; /* Parent Context: max specifications 1M */ - u32 max_cqs; - u16 max_srqs; - u32 srq_id_start; - u32 max_mpts; -}; - -/* ToE services */ -struct toe_service_cap { - struct dev_toe_svc_cap dev_toe_cap; - - bool alloc_flag; - u32 pctx_sz; /* 1KB */ - u32 scqc_sz; /* 64B */ -}; - -/* PF FC service resource structure defined */ -struct dev_fc_svc_cap { - /* PF Parent QPC */ - u32 max_parent_qpc_num; /* max number is 2048 */ - - /* PF Child QPC */ - u32 max_child_qpc_num; /* max number is 2048 */ - u32 child_qpc_id_start; - - /* PF SCQ */ - u32 scq_num; /* 16 */ - - /* PF supports SRQ */ - u32 srq_num; /* Number of SRQ is 2 */ - - u8 vp_id_start; - u8 vp_id_end; -}; - -/* FC services */ -struct fc_service_cap { - struct dev_fc_svc_cap dev_fc_cap; - - /* Parent QPC */ - u32 parent_qpc_size; /* 256B */ - - /* Child QPC */ - u32 child_qpc_size; /* 256B */ - - /* SQ */ - u32 sqe_size; /* 128B(in linked list mode) */ - - /* SCQ */ - u32 scqc_size; /* Size of the Context 32B */ - u32 scqe_size; /* 64B */ - - /* SRQ */ - u32 srqc_size; /* Size of SRQ Context (64B) */ - u32 srqe_size; /* 32B */ -}; - -struct dev_roce_svc_own_cap { - u32 max_qps; - u32 max_cqs; - u32 max_srqs; - u32 max_mpts; - u32 max_drc_qps; - - u32 cmtt_cl_start; - u32 cmtt_cl_end; - u32 cmtt_cl_sz; - - u32 dmtt_cl_start; - u32 dmtt_cl_end; - u32 dmtt_cl_sz; - - u32 wqe_cl_start; - u32 wqe_cl_end; - u32 wqe_cl_sz; - - u32 qpc_entry_sz; - u32 max_wqes; - u32 max_rq_sg; - u32 max_sq_inline_data_sz; - u32 max_rq_desc_sz; - - u32 rdmarc_entry_sz; - u32 max_qp_init_rdma; - u32 max_qp_dest_rdma; - - u32 max_srq_wqes; - u32 reserved_srqs; - u32 max_srq_sge; - u32 srqc_entry_sz; - - u32 max_msg_sz; /* Message size 2GB */ -}; - -/* RDMA service capability structure */ -struct dev_rdma_svc_cap { - /* ROCE service unique parameter structure */ - struct dev_roce_svc_own_cap roce_own_cap; -}; - -/* Defines the RDMA service capability flag */ -enum { - RDMA_BMME_FLAG_LOCAL_INV = (1 << 0), - RDMA_BMME_FLAG_REMOTE_INV = (1 << 1), - RDMA_BMME_FLAG_FAST_REG_WR = (1 << 2), - RDMA_BMME_FLAG_RESERVED_LKEY = (1 << 3), - RDMA_BMME_FLAG_TYPE_2_WIN = (1 << 4), - RDMA_BMME_FLAG_WIN_TYPE_2B = (1 << 5), - - RDMA_DEV_CAP_FLAG_XRC = (1 << 6), - RDMA_DEV_CAP_FLAG_MEM_WINDOW = (1 << 7), - RDMA_DEV_CAP_FLAG_ATOMIC = (1 << 8), - RDMA_DEV_CAP_FLAG_APM = (1 << 9), -}; - -/* RDMA services */ -struct rdma_service_cap { - struct dev_rdma_svc_cap dev_rdma_cap; - - u8 log_mtt; /* 1. the number of MTT PA must be integer power of 2 - * 2. represented by logarithm. Each MTT table can - * contain 1, 2, 4, 8, and 16 PA) - */ - /* todo: need to check whether related to max_mtt_seg */ - u32 num_mtts; /* Number of MTT table (4M), - * is actually MTT seg number - */ - u32 log_mtt_seg; - u32 mtt_entry_sz; /* MTT table size 8B, including 1 PA(64bits) */ - u32 mpt_entry_sz; /* MPT table size (64B) */ - - u32 dmtt_cl_start; - u32 dmtt_cl_end; - u32 dmtt_cl_sz; - - u8 log_rdmarc; /* 1. the number of RDMArc PA must be integer power of 2 - * 2. represented by logarithm. Each MTT table can - * contain 1, 2, 4, 8, and 16 PA) - */ - - u32 reserved_qps; /* Number of reserved QP */ - u32 max_sq_sg; /* Maximum SGE number of SQ (8) */ - u32 max_sq_desc_sz; /* WQE maximum size of SQ(1024B), inline maximum - * size if 960B(944B aligned to the 960B), - * 960B=>wqebb alignment=>1024B - */ - u32 wqebb_size; /* Currently, the supports 64B and 128B, - * defined as 64Bytes - */ - - u32 max_cqes; /* Size of the depth of the CQ (64K-1) */ - u32 reserved_cqs; /* Number of reserved CQ */ - u32 cqc_entry_sz; /* Size of the CQC (64B/128B) */ - u32 cqe_size; /* Size of CQE (32B) */ - - u32 reserved_mrws; /* Number of reserved MR/MR Window */ - - u32 max_fmr_maps; /* max MAP of FMR, - * (1 << (32-ilog2(num_mpt)))-1; - */ - - /* todo: max value needs to be confirmed */ - /* MTT table number of Each MTT seg(3) */ - - u32 log_rdmarc_seg; /* table number of each RDMArc seg(3) */ - - /* Timeout time. Formula:Tr=4.096us*2(local_ca_ack_delay), [Tr,4Tr] */ - u32 local_ca_ack_delay; - u32 num_ports; /* Physical port number */ - - u32 db_page_size; /* Size of the DB (4KB) */ - u32 direct_wqe_size; /* Size of the DWQE (256B) */ - - u32 num_pds; /* Maximum number of PD (128K) */ - u32 reserved_pds; /* Number of reserved PD */ - u32 max_xrcds; /* Maximum number of xrcd (64K) */ - u32 reserved_xrcds; /* Number of reserved xrcd */ - - u32 max_gid_per_port; /* gid number (16) of each port */ - u32 gid_entry_sz; /* RoCE v2 GID table is 32B, - * compatible RoCE v1 expansion - */ - - u32 reserved_lkey; /* local_dma_lkey */ - u32 num_comp_vectors; /* Number of complete vector (32) */ - u32 page_size_cap; /* Supports 4K,8K,64K,256K,1M and 4M page_size */ - - u32 flags; /* RDMA some identity */ - u32 max_frpl_len; /* Maximum number of pages frmr registration */ - u32 max_pkeys; /* Number of supported pkey group */ -}; - -/* PF OVS service resource structure defined */ -struct dev_ovs_svc_cap { - u32 max_pctxs; /* Parent Context: max specifications 1M */ - u8 dynamic_qp_en; - u8 fake_vf_num; - u16 fake_vf_start_id; -}; - -/* OVS services */ -struct ovs_service_cap { - struct dev_ovs_svc_cap dev_ovs_cap; - - u32 pctx_sz; /* 512B */ -}; - -/* PF IPsec service resource structure defined */ -struct dev_ipsec_svc_cap { - /* PF resources */ - u32 max_sa_ctxs; /* Parent Context: max specifications 8192 */ -}; - -/* IPsec services */ -struct ipsec_service_cap { - struct dev_ipsec_svc_cap dev_ipsec_cap; - u32 sactx_sz; /* 512B */ -}; - -/* Defines the IRQ information structure */ -struct irq_info { - u16 msix_entry_idx; /* IRQ corresponding index number */ - u32 irq_id; /* the IRQ number from OS */ -}; - -struct interrupt_info { - u32 lli_set; - u32 interrupt_coalesc_set; - u16 msix_index; - u8 lli_credit_limit; - u8 lli_timer_cfg; - u8 pending_limt; - u8 coalesc_timer_cfg; - u8 resend_timer_cfg; -}; - -enum sphw_msix_state { - SPHW_MSIX_ENABLE, - SPHW_MSIX_DISABLE, -}; - -enum sphw_msix_auto_mask { - SPHW_SET_MSIX_AUTO_MASK, - SPHW_CLR_MSIX_AUTO_MASK, -}; - -enum func_type { - TYPE_PF, - TYPE_VF, - TYPE_PPF, - TYPE_UNKNOWN, -}; - -struct sphw_init_para { - /* Record spnic_pcidev or NDIS_Adapter pointer address */ - void *adapter_hdl; - /* Record pcidev or Handler pointer address - * for example: ioremap interface input parameter - */ - void *pcidev_hdl; - /* Record pcidev->dev or Handler pointer address which used to - * dma address application or dev_err print the parameter - */ - void *dev_hdl; - - /* Configure virtual address, PF is bar1, VF is bar0/1 */ - void *cfg_reg_base; - /* interrupt configuration register address, PF is bar2, VF is bar2/3 - */ - void *intr_reg_base; - /* for PF bar3 virtual address, if function is VF should set to NULL */ - void *mgmt_reg_base; - - u64 db_dwqe_len; - u64 db_base_phy; - /* the doorbell address, bar4/5 higher 4M space */ - void *db_base; - /* direct wqe 4M, follow the doorbell address space */ - void *dwqe_mapping; - void **hwdev; - void *chip_node; - /* In bmgw x86 host, driver can't send message to mgmt cpu directly, - * need to trasmit message ppf mbox to bmgw arm host. - */ - void *ppf_hwdev; -}; - -/* B200 config BAR45 4MB, DB & DWQE both 2MB */ -#define SPHW_DB_DWQE_SIZE 0x00400000 - -/* db/dwqe page size: 4K */ -#define SPHW_DB_PAGE_SIZE 0x00001000ULL -#define SPHW_DWQE_OFFSET 0x00000800ULL - -#define SPHW_DB_MAX_AREAS (SPHW_DB_DWQE_SIZE / SPHW_DB_PAGE_SIZE) - -#ifndef IFNAMSIZ -#define IFNAMSIZ 16 -#endif -#define MAX_FUNCTION_NUM 4096 -#define SPHW_MAX_COS 8 - -struct card_node { - struct list_head node; - struct list_head func_list; - char chip_name[IFNAMSIZ]; - void *log_info; - void *dbgtool_info; - void *func_handle_array[MAX_FUNCTION_NUM]; - unsigned char bus_num; - u8 func_num; - bool up_bitmap_setted; - u8 valid_up_bitmap; -}; - -#define FAULT_SHOW_STR_LEN 16 - -enum sphw_fault_source_type { - /* same as FAULT_TYPE_CHIP */ - SPHW_FAULT_SRC_HW_MGMT_CHIP = 0, - /* same as FAULT_TYPE_UCODE */ - SPHW_FAULT_SRC_HW_MGMT_UCODE, - /* same as FAULT_TYPE_MEM_RD_TIMEOUT */ - SPHW_FAULT_SRC_HW_MGMT_MEM_RD_TIMEOUT, - /* same as FAULT_TYPE_MEM_WR_TIMEOUT */ - SPHW_FAULT_SRC_HW_MGMT_MEM_WR_TIMEOUT, - /* same as FAULT_TYPE_REG_RD_TIMEOUT */ - SPHW_FAULT_SRC_HW_MGMT_REG_RD_TIMEOUT, - /* same as FAULT_TYPE_REG_WR_TIMEOUT */ - SPHW_FAULT_SRC_HW_MGMT_REG_WR_TIMEOUT, - SPHW_FAULT_SRC_SW_MGMT_UCODE, - SPHW_FAULT_SRC_MGMT_WATCHDOG, - SPHW_FAULT_SRC_MGMT_RESET = 8, - SPHW_FAULT_SRC_HW_PHY_FAULT, - SPHW_FAULT_SRC_TX_PAUSE_EXCP, - SPHW_FAULT_SRC_PCIE_LINK_DOWN = 20, - SPHW_FAULT_SRC_HOST_HEARTBEAT_LOST = 21, - SPHW_FAULT_SRC_TX_TIMEOUT, - SPHW_FAULT_SRC_TYPE_MAX, -}; - -union sphw_fault_hw_mgmt { - u32 val[4]; - /* valid only type == FAULT_TYPE_CHIP */ - struct { - u8 node_id; - /* enum sphw_fault_err_level */ - u8 err_level; - u16 err_type; - u32 err_csr_addr; - u32 err_csr_value; - /* func_id valid only if err_level == FAULT_LEVEL_SERIOUS_FLR */ - u16 func_id; - u16 rsvd2; - } chip; - - /* valid only if type == FAULT_TYPE_UCODE */ - struct { - u8 cause_id; - u8 core_id; - u8 c_id; - u8 rsvd3; - u32 epc; - u32 rsvd4; - u32 rsvd5; - } ucode; - - /* valid only if type == FAULT_TYPE_MEM_RD_TIMEOUT || - * FAULT_TYPE_MEM_WR_TIMEOUT - */ - struct { - u32 err_csr_ctrl; - u32 err_csr_data; - u32 ctrl_tab; - u32 mem_index; - } mem_timeout; - - /* valid only if type == FAULT_TYPE_REG_RD_TIMEOUT || - * FAULT_TYPE_REG_WR_TIMEOUT - */ - struct { - u32 err_csr; - u32 rsvd6; - u32 rsvd7; - u32 rsvd8; - } reg_timeout; - - struct { - /* 0: read; 1: write */ - u8 op_type; - u8 port_id; - u8 dev_ad; - u8 rsvd9; - u32 csr_addr; - u32 op_data; - u32 rsvd10; - } phy_fault; -}; - -/* defined by chip */ -struct sphw_fault_event { - /* enum sphw_fault_type */ - u8 type; - u8 fault_level; /* sdk write fault level for uld event */ - u8 rsvd0[2]; - union sphw_fault_hw_mgmt event; -}; - -struct sphw_cmd_fault_event { - u8 status; - u8 version; - u8 rsvd0[6]; - struct sphw_fault_event event; -}; - -enum sphw_event_type { - SPHW_EVENT_LINK_DOWN = 0, - SPHW_EVENT_LINK_UP = 1, - SPHW_EVENT_FAULT = 3, - SPHW_EVENT_DCB_STATE_CHANGE = 5, - SPHW_EVENT_INIT_MIGRATE_PF, - SPHW_EVENT_SRIOV_STATE_CHANGE, - SPHW_EVENT_PORT_MODULE_EVENT, - SPHW_EVENT_PCIE_LINK_DOWN, - SPHW_EVENT_HEART_LOST, -}; - -struct sphw_event_link_info { - u8 valid; - u8 port_type; - u8 autoneg_cap; - u8 autoneg_state; - u8 duplex; - u8 speed; -}; - -struct sphw_dcb_info { - u8 dcb_on; - u8 default_cos; - u8 up_cos[SPHW_MAX_COS]; -}; - -struct sphw_sriov_state_info { - u8 enable; - u16 num_vfs; -}; - -enum link_err_type { - LINK_ERR_MODULE_UNRECOGENIZED, - LINK_ERR_NUM, -}; - -enum port_module_event_type { - SPHW_PORT_MODULE_CABLE_PLUGGED, - SPHW_PORT_MODULE_CABLE_UNPLUGGED, - SPHW_PORT_MODULE_LINK_ERR, - SPHW_PORT_MODULE_MAX_EVENT, -}; - -struct sphw_port_module_event { - enum port_module_event_type type; - enum link_err_type err_type; -}; - -struct sphw_event_info { - enum sphw_event_type type; - union { - struct sphw_event_link_info link_info; - struct sphw_fault_event info; - struct sphw_dcb_info dcb_state; - struct sphw_sriov_state_info sriov_state; - struct sphw_port_module_event module_event; - }; -}; - -typedef void (*sphw_event_handler)(void *handle, struct sphw_event_info *event); - -/* * - * @brief sphw_event_register - register hardware event - * @param dev: device pointer to hwdev - * @param pri_handle: private data will be used by the callback - * @param callback: callback function - */ -void sphw_event_register(void *dev, void *pri_handle, sphw_event_handler callback); - -/* * - * @brief sphw_event_unregister - unregister hardware event - * @param dev: device pointer to hwdev - */ -void sphw_event_unregister(void *dev); - -/* * - * @brief sphw_set_msix_auto_mask_state - set msix auto mask function - * @param hwdev: device pointer to hwdev - * @param msix_idx: msix id - * @param flag: msix auto_mask flag, 1-enable, 2-clear - */ -void sphw_set_msix_auto_mask_state(void *hwdev, u16 msix_idx, enum sphw_msix_auto_mask flag); - -/* * - * @brief sphw_set_msix_state - set msix state - * @param hwdev: device pointer to hwdev - * @param msix_idx: msix id - * @param flag: msix state flag, 0-enable, 1-disable - */ -void sphw_set_msix_state(void *hwdev, u16 msix_idx, enum sphw_msix_state flag); - -/* * - * @brief sphw_misx_intr_clear_resend_bit - clear msix resend bit - * @param hwdev: device pointer to hwdev - * @param msix_idx: msix id - * @param clear_resend_en: 1-clear - */ -void sphw_misx_intr_clear_resend_bit(void *hwdev, u16 msix_idx, u8 clear_resend_en); - -/* * - * @brief sphw_set_interrupt_cfg_direct - set interrupt cfg - * @param hwdev: device pointer to hwdev - * @param interrupt_para: interrupt info - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_set_interrupt_cfg_direct(void *hwdev, struct interrupt_info *interrupt_para, u16 channel); - -int sphw_set_interrupt_cfg(void *hwdev, struct interrupt_info interrupt_info, u16 channel); - -/* * - * @brief sphw_get_interrupt_cfg - get interrupt cfg - * @param dev: device pointer to hwdev - * @param info: interrupt info - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_get_interrupt_cfg(void *dev, struct interrupt_info *info, u16 channel); - -/* * - * @brief sphw_alloc_irqs - alloc irq - * @param hwdev: device pointer to hwdev - * @param type: service type - * @param num: alloc number - * @param irq_info_array: alloc irq info - * @param act_num: alloc actual number - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_alloc_irqs(void *hwdev, enum sphw_service_type type, u16 num, - struct irq_info *irq_info_array, u16 *act_num); - -/* * - * @brief sphw_free_irq - free irq - * @param hwdev: device pointer to hwdev - * @param type: service type - * @param irq_id: irq id - */ -void sphw_free_irq(void *hwdev, enum sphw_service_type type, u32 irq_id); - -/* * - * @brief sphw_alloc_ceqs - alloc ceqs - * @param hwdev: device pointer to hwdev - * @param type: service type - * @param num: alloc ceq number - * @param ceq_id_array: alloc ceq_id_array - * @param act_num: alloc actual number - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_alloc_ceqs(void *hwdev, enum sphw_service_type type, int num, int *ceq_id_array, - int *act_num); - -/* * - * @brief sphw_free_irq - free ceq - * @param hwdev: device pointer to hwdev - * @param type: service type - * @param irq_id: ceq id - */ -void sphw_free_ceq(void *hwdev, enum sphw_service_type type, int ceq_id); - -/* * - * @brief sphw_get_pcidev_hdl - get pcidev_hdl - * @param hwdev: device pointer to hwdev - * @retval non-null: success - * @retval null: failure - */ -void *sphw_get_pcidev_hdl(void *hwdev); - -/* * - * @brief sphw_ppf_idx - get ppf id - * @param hwdev: device pointer to hwdev - * @retval ppf id - */ -u8 sphw_ppf_idx(void *hwdev); - -/* * - * @brief sphw_get_chip_present_flag - get chip present flag - * @param hwdev: device pointer to hwdev - * @retval 1: chip is present - * @retval 0: chip is absent - */ -int sphw_get_chip_present_flag(const void *hwdev); - -/* * - * @brief sphw_support_nic - function support nic - * @param hwdev: device pointer to hwdev - * @param cap: nic service capbility - * @retval true: function support nic - * @retval false: function not support nic - */ -bool sphw_support_nic(void *hwdev, struct nic_service_cap *cap); - -/* * - * @brief sphw_support_ipsec - function support ipsec - * @param hwdev: device pointer to hwdev - * @param cap: ipsec service capbility - * @retval true: function support ipsec - * @retval false: function not support ipsec - */ -bool sphw_support_ipsec(void *hwdev, struct ipsec_service_cap *cap); - -/* * - * @brief sphw_support_roce - function support roce - * @param hwdev: device pointer to hwdev - * @param cap: roce service capbility - * @retval true: function support roce - * @retval false: function not support roce - */ -bool sphw_support_roce(void *hwdev, struct rdma_service_cap *cap); - -/* * - * @brief sphw_support_fc - function support fc - * @param hwdev: device pointer to hwdev - * @param cap: fc service capbility - * @retval true: function support fc - * @retval false: function not support fc - */ -bool sphw_support_fc(void *hwdev, struct fc_service_cap *cap); - -/* * - * @brief sphw_support_rdma - function support rdma - * @param hwdev: device pointer to hwdev - * @param cap: rdma service capbility - * @retval true: function support rdma - * @retval false: function not support rdma - */ -bool sphw_support_rdma(void *hwdev, struct rdma_service_cap *cap); - -/* * - * @brief sphw_support_ovs - function support ovs - * @param hwdev: device pointer to hwdev - * @param cap: ovs service capbility - * @retval true: function support ovs - * @retval false: function not support ovs - */ -bool sphw_support_ovs(void *hwdev, struct ovs_service_cap *cap); - -/* * - * @brief sphw_support_toe - sync time to hardware - * @param hwdev: device pointer to hwdev - * @param cap: toe service capbility - * @retval zero: success - * @retval non-zero: failure - */ -bool sphw_support_toe(void *hwdev, struct toe_service_cap *cap); - -/* * - * @brief sphw_sync_time - sync time to hardware - * @param hwdev: device pointer to hwdev - * @param time: time to sync - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_sync_time(void *hwdev, u64 time); - -/* * - * @brief sphw_disable_mgmt_msg_report - disable mgmt report msg - * @param hwdev: device pointer to hwdev - */ -void sphw_disable_mgmt_msg_report(void *hwdev); - -/* * - * @brief sphw_func_for_mgmt - get function service type - * @param hwdev: device pointer to hwdev - * @retval true: function for mgmt - * @retval false: function is not for mgmt - */ -bool sphw_func_for_mgmt(void *hwdev); - -/* * - * @brief sphw_set_pcie_order_cfg - set pcie order cfg - * @param handle: device pointer to hwdev - */ -void sphw_set_pcie_order_cfg(void *handle); - -/* * - * @brief sphw_init_hwdev - call to init hwdev - * @param para: device pointer to para - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_init_hwdev(struct sphw_init_para *para); - -/* * - * @brief sphw_free_hwdev - free hwdev - * @param hwdev: device pointer to hwdev - */ -void sphw_free_hwdev(void *hwdev); - -/* * - * @brief sphw_detect_hw_present - detect hardware present - * @param hwdev: device pointer to hwdev - */ -void sphw_detect_hw_present(void *hwdev); - -/* * - * @brief sphw_record_pcie_error - record pcie error - * @param hwdev: device pointer to hwdev - */ -void sphw_record_pcie_error(void *hwdev); - -/* * - * @brief sphw_shutdown_hwdev - shutdown hwdev - * @param hwdev: device pointer to hwdev - */ -void sphw_shutdown_hwdev(void *hwdev); - -/* * - * @brief sphw_get_mgmt_version - get management cpu version - * @param hwdev: device pointer to hwdev - * @param mgmt_ver: output management version - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_get_mgmt_version(void *hwdev, u8 *mgmt_ver, u8 version_size, u16 channel); - -/* * - * @brief sphw_get_fw_version - get firmware version - * @param hwdev: device pointer to hwdev - * @param fw_ver: firmware version - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_get_fw_version(void *hwdev, struct sphw_fw_version *fw_ver, u16 channel); - -/* * - * @brief sphw_global_func_id - get global function id - * @param hwdev: device pointer to hwdev - * @retval global function id - */ -u16 sphw_global_func_id(void *hwdev); - -/* * - * @brief sphw_vector_to_eqn - vector to eq id - * @param hwdev: device pointer to hwdev - * @param type: service type - * @param vector: vertor - * @retval eq id - */ -int sphw_vector_to_eqn(void *hwdev, enum sphw_service_type type, int vector); - -/* * - * @brief sphw_glb_pf_vf_offset - get vf offset id of pf - * @param hwdev: device pointer to hwdev - * @retval vf offset id - */ -u16 sphw_glb_pf_vf_offset(void *hwdev); - -/* * - * @brief sphw_pf_id_of_vf - get pf id of vf - * @param hwdev: device pointer to hwdev - * @retval pf id - */ -u8 sphw_pf_id_of_vf(void *hwdev); - -/* * - * @brief sphw_func_type - get function type - * @param hwdev: device pointer to hwdev - * @retval function type - */ -enum func_type sphw_func_type(void *hwdev); - -/* * - * @brief sphw_host_oq_id_mask - get oq id - * @param hwdev: device pointer to hwdev - * @retval oq id - */ -u8 sphw_host_oq_id_mask(void *hwdev); - -/* * - * @brief sphw_host_id - get host id - * @param hwdev: device pointer to hwdev - * @retval host id - */ -u8 sphw_host_id(void *hwdev); - -/* * - * @brief sphw_func_max_qnum - get host total function number - * @param hwdev: device pointer to hwdev - * @retval non-zero: host total function number - * @retval zero: failure - */ -u16 sphw_host_total_func(void *hwdev); - -/* * - * @brief sphw_func_max_qnum - get max nic queue number - * @param hwdev: device pointer to hwdev - * @retval non-zero: max nic queue number - * @retval zero: failure - */ -u16 sphw_func_max_nic_qnum(void *hwdev); - -/* * - * @brief sphw_func_max_qnum - get max queue number - * @param hwdev: device pointer to hwdev - * @retval non-zero: max queue number - * @retval zero: failure - */ -u16 sphw_func_max_qnum(void *hwdev); - -/* * - * @brief sphw_er_id - get ep id - * @param hwdev: device pointer to hwdev - * @retval ep id - */ -u8 sphw_ep_id(void *hwdev); /* Obtain service_cap.ep_id */ - -/* * - * @brief sphw_er_id - get er id - * @param hwdev: device pointer to hwdev - * @retval er id - */ -u8 sphw_er_id(void *hwdev); /* Obtain service_cap.er_id */ - -/* * - * @brief sphw_physical_port_id - get physical port id - * @param hwdev: device pointer to hwdev - * @retval physical port id - */ -u8 sphw_physical_port_id(void *hwdev); /* Obtain service_cap.port_id */ - -/* * - * @brief sphw_func_max_vf - get vf number - * @param hwdev: device pointer to hwdev - * @retval non-zero: vf number - * @retval zero: failure - */ -u16 sphw_func_max_vf(void *hwdev); /* Obtain service_cap.max_vf */ - -/* @brief sphw_max_pf_num - get global max pf number - */ -u8 sphw_max_pf_num(void *hwdev); - -/* * - * @brief sphw_host_pf_num - get current host pf number - * @param hwdev: device pointer to hwdev - * @retval non-zero: pf number - * @retval zero: failure - */ -u32 sphw_host_pf_num(void *hwdev); /* Obtain service_cap.pf_num */ - -/* * - * @brief sphw_pcie_itf_id - get pcie port id - * @param hwdev: device pointer to hwdev - * @retval pcie port id - */ -u8 sphw_pcie_itf_id(void *hwdev); - -/* * - * @brief sphw_vf_in_pf - get vf offset in pf - * @param hwdev: device pointer to hwdev - * @retval vf offset in pf - */ -u8 sphw_vf_in_pf(void *hwdev); - -/* * - * @brief sphw_cos_valid_bitmap - get cos valid bitmap - * @param hwdev: device pointer to hwdev - * @retval non-zero: valid cos bit map - * @retval zero: failure - */ -u8 sphw_cos_valid_bitmap(void *hwdev); - -/* * - * @brief sphw_get_card_present_state - get card present state - * @param hwdev: device pointer to hwdev - * @param card_present_state: return card present state - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_get_card_present_state(void *hwdev, bool *card_present_state); - -/* * - * @brief sphw_func_rx_tx_flush - function flush - * @param hwdev: device pointer to hwdev - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_func_rx_tx_flush(void *hwdev, u16 channel); - -/* * - * @brief sphw_flush_mgmt_workq - when remove function should flush work queue - * @param hwdev: device pointer to hwdev - */ -void sphw_flush_mgmt_workq(void *hwdev); - -/* @brief sphw_ceq_num get toe ceq num - */ -u8 sphw_ceq_num(void *hwdev); - -/* * - * @brief sphw_intr_num get intr num - */ -u16 sphw_intr_num(void *hwdev); - -/* @brief sphw_flexq_en get flexq en - */ -u8 sphw_flexq_en(void *hwdev); - -/** - * @brief sphw_fault_event_report - report fault event - * @param hwdev: device pointer to hwdev - * @param src: fault event source, reference to enum sphw_fault_source_type - * @param level: fault level, reference to enum sphw_fault_err_level - */ -void sphw_fault_event_report(void *hwdev, u16 src, u16 level); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_csr.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_csr.h deleted file mode 100644 index d283c1456615..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_csr.h +++ /dev/null @@ -1,158 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_CSR_H -#define SPHW_CSR_H - -/* bit30/bit31 for bar index flag - * 00: bar0 - * 01: bar1 - * 10: bar2 - * 11: bar3 - */ -#define SPHW_CFG_REGS_FLAG 0x40000000 - -#define SPHW_MGMT_REGS_FLAG 0xC0000000 - -#define SPHW_REGS_FLAG_MAKS 0x3FFFFFFF - -#define SPHW_VF_CFG_REG_OFFSET 0x2000 - -#define SPHW_HOST_CSR_BASE_ADDR (SPHW_MGMT_REGS_FLAG + 0x6000) -#define SPHW_CSR_GLOBAL_BASE_ADDR (SPHW_MGMT_REGS_FLAG + 0x6400) - -/* HW interface registers */ -#define SPHW_CSR_FUNC_ATTR0_ADDR (SPHW_CFG_REGS_FLAG + 0x0) -#define SPHW_CSR_FUNC_ATTR1_ADDR (SPHW_CFG_REGS_FLAG + 0x4) -#define SPHW_CSR_FUNC_ATTR2_ADDR (SPHW_CFG_REGS_FLAG + 0x8) -#define SPHW_CSR_FUNC_ATTR3_ADDR (SPHW_CFG_REGS_FLAG + 0xC) -#define SPHW_CSR_FUNC_ATTR4_ADDR (SPHW_CFG_REGS_FLAG + 0x10) -#define SPHW_CSR_FUNC_ATTR5_ADDR (SPHW_CFG_REGS_FLAG + 0x14) -#define SPHW_CSR_FUNC_ATTR6_ADDR (SPHW_CFG_REGS_FLAG + 0x18) - -#define SPHW_FUNC_CSR_MAILBOX_DATA_OFF 0x80 -#define SPHW_FUNC_CSR_MAILBOX_CONTROL_OFF \ - (SPHW_CFG_REGS_FLAG + 0x0100) -#define SPHW_FUNC_CSR_MAILBOX_INT_OFFSET_OFF \ - (SPHW_CFG_REGS_FLAG + 0x0104) -#define SPHW_FUNC_CSR_MAILBOX_RESULT_H_OFF \ - (SPHW_CFG_REGS_FLAG + 0x0108) -#define SPHW_FUNC_CSR_MAILBOX_RESULT_L_OFF \ - (SPHW_CFG_REGS_FLAG + 0x010C) - -#define SPHW_PPF_ELECTION_OFFSET 0x0 -#define SPHW_MPF_ELECTION_OFFSET 0x20 - -#define SPHW_CSR_PPF_ELECTION_ADDR \ - (SPHW_HOST_CSR_BASE_ADDR + SPHW_PPF_ELECTION_OFFSET) - -#define SPHW_CSR_GLOBAL_MPF_ELECTION_ADDR \ - (SPHW_HOST_CSR_BASE_ADDR + SPHW_MPF_ELECTION_OFFSET) - -#define SPHW_CSR_FUNC_PPF_ELECT_BASE_ADDR (SPHW_CFG_REGS_FLAG + 0x60) -#define SPHW_CSR_FUNC_PPF_ELECT_PORT_STRIDE 0x4 - -#define SPHW_CSR_FUNC_PPF_ELECT(host_idx) \ - (SPHW_CSR_FUNC_PPF_ELECT_BASE_ADDR + \ - (host_idx) * SPHW_CSR_FUNC_PPF_ELECT_PORT_STRIDE) - -#define SPHW_CSR_DMA_ATTR_TBL_ADDR (SPHW_CFG_REGS_FLAG + 0x380) -#define SPHW_CSR_DMA_ATTR_INDIR_IDX_ADDR (SPHW_CFG_REGS_FLAG + 0x390) - -/* MSI-X registers */ -#define SPHW_CSR_MSIX_INDIR_IDX_ADDR (SPHW_CFG_REGS_FLAG + 0x310) -#define SPHW_CSR_MSIX_CTRL_ADDR (SPHW_CFG_REGS_FLAG + 0x300) -#define SPHW_CSR_MSIX_CNT_ADDR (SPHW_CFG_REGS_FLAG + 0x304) -#define SPHW_CSR_FUNC_MSI_CLR_WR_ADDR (SPHW_CFG_REGS_FLAG + 0x58) - -#define SPHW_MSI_CLR_INDIR_RESEND_TIMER_CLR_SHIFT 0 -#define SPHW_MSI_CLR_INDIR_INT_MSK_SET_SHIFT 1 -#define SPHW_MSI_CLR_INDIR_INT_MSK_CLR_SHIFT 2 -#define SPHW_MSI_CLR_INDIR_AUTO_MSK_SET_SHIFT 3 -#define SPHW_MSI_CLR_INDIR_AUTO_MSK_CLR_SHIFT 4 -#define SPHW_MSI_CLR_INDIR_SIMPLE_INDIR_IDX_SHIFT 22 - -#define SPHW_MSI_CLR_INDIR_RESEND_TIMER_CLR_MASK 0x1U -#define SPHW_MSI_CLR_INDIR_INT_MSK_SET_MASK 0x1U -#define SPHW_MSI_CLR_INDIR_INT_MSK_CLR_MASK 0x1U -#define SPHW_MSI_CLR_INDIR_AUTO_MSK_SET_MASK 0x1U -#define SPHW_MSI_CLR_INDIR_AUTO_MSK_CLR_MASK 0x1U -#define SPHW_MSI_CLR_INDIR_SIMPLE_INDIR_IDX_MASK 0x3FFU - -#define SPHW_MSI_CLR_INDIR_SET(val, member) \ - (((val) & SPHW_MSI_CLR_INDIR_##member##_MASK) << \ - SPHW_MSI_CLR_INDIR_##member##_SHIFT) - -/* EQ registers */ -#define SPHW_AEQ_INDIR_IDX_ADDR (SPHW_CFG_REGS_FLAG + 0x210) -#define SPHW_CEQ_INDIR_IDX_ADDR (SPHW_CFG_REGS_FLAG + 0x290) - -#define SPHW_EQ_INDIR_IDX_ADDR(type) \ - ((type == SPHW_AEQ) ? SPHW_AEQ_INDIR_IDX_ADDR : SPHW_CEQ_INDIR_IDX_ADDR) - -#define SPHW_AEQ_MTT_OFF_BASE_ADDR (SPHW_CFG_REGS_FLAG + 0x240) -#define SPHW_CEQ_MTT_OFF_BASE_ADDR (SPHW_CFG_REGS_FLAG + 0x2C0) - -#define SPHW_CSR_EQ_PAGE_OFF_STRIDE 8 - -#define SPHW_AEQ_HI_PHYS_ADDR_REG(pg_num) \ - (SPHW_AEQ_MTT_OFF_BASE_ADDR + \ - (pg_num) * SPHW_CSR_EQ_PAGE_OFF_STRIDE) - -#define SPHW_AEQ_LO_PHYS_ADDR_REG(pg_num) \ - (SPHW_AEQ_MTT_OFF_BASE_ADDR + \ - (pg_num) * SPHW_CSR_EQ_PAGE_OFF_STRIDE + 4) - -#define SPHW_CEQ_HI_PHYS_ADDR_REG(pg_num) \ - (SPHW_CEQ_MTT_OFF_BASE_ADDR + \ - (pg_num) * SPHW_CSR_EQ_PAGE_OFF_STRIDE) - -#define SPHW_CEQ_LO_PHYS_ADDR_REG(pg_num) \ - (SPHW_CEQ_MTT_OFF_BASE_ADDR + \ - (pg_num) * SPHW_CSR_EQ_PAGE_OFF_STRIDE + 4) - -#define SPHW_CSR_AEQ_CTRL_0_ADDR (SPHW_CFG_REGS_FLAG + 0x200) -#define SPHW_CSR_AEQ_CTRL_1_ADDR (SPHW_CFG_REGS_FLAG + 0x204) -#define SPHW_CSR_AEQ_CONS_IDX_ADDR (SPHW_CFG_REGS_FLAG + 0x208) -#define SPHW_CSR_AEQ_PROD_IDX_ADDR (SPHW_CFG_REGS_FLAG + 0x20C) -#define SPHW_CSR_AEQ_CI_SIMPLE_INDIR_ADDR (SPHW_CFG_REGS_FLAG + 0x50) - -#define SPHW_CSR_CEQ_CTRL_0_ADDR (SPHW_CFG_REGS_FLAG + 0x280) -#define SPHW_CSR_CEQ_CTRL_1_ADDR (SPHW_CFG_REGS_FLAG + 0x284) -#define SPHW_CSR_CEQ_CONS_IDX_ADDR (SPHW_CFG_REGS_FLAG + 0x288) -#define SPHW_CSR_CEQ_PROD_IDX_ADDR (SPHW_CFG_REGS_FLAG + 0x28c) -#define SPHW_CSR_CEQ_CI_SIMPLE_INDIR_ADDR (SPHW_CFG_REGS_FLAG + 0x54) - -/* API CMD registers */ -#define SPHW_CSR_API_CMD_BASE (SPHW_MGMT_REGS_FLAG + 0x2000) - -#define SPHW_CSR_API_CMD_STRIDE 0x80 - -#define SPHW_CSR_API_CMD_CHAIN_HEAD_HI_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0x0 + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#define SPHW_CSR_API_CMD_CHAIN_HEAD_LO_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0x4 + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#define SPHW_CSR_API_CMD_STATUS_HI_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0x8 + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#define SPHW_CSR_API_CMD_STATUS_LO_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0xC + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#define SPHW_CSR_API_CMD_CHAIN_NUM_CELLS_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0x10 + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#define SPHW_CSR_API_CMD_CHAIN_CTRL_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0x14 + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#define SPHW_CSR_API_CMD_CHAIN_PI_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0x1C + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#define SPHW_CSR_API_CMD_CHAIN_REQ_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0x20 + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#define SPHW_CSR_API_CMD_STATUS_0_ADDR(idx) \ - (SPHW_CSR_API_CMD_BASE + 0x30 + (idx) * SPHW_CSR_API_CMD_STRIDE) - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_eqs.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_eqs.c deleted file mode 100644 index 24c55d656f9c..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_eqs.c +++ /dev/null @@ -1,1272 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/workqueue.h> -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/dma-mapping.h> -#include <linux/module.h> -#include <linux/spinlock.h> -#include <linux/delay.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_common.h" -#include "sphw_hwdev.h" -#include "sphw_hwif.h" -#include "sphw_hw.h" -#include "sphw_csr.h" -#include "sphw_hw_comm.h" -#include "sphw_prof_adap.h" -#include "sphw_eqs.h" - -#define SPHW_EQS_WQ_NAME "sphw_eqs" - -#define AEQ_CTRL_0_INTR_IDX_SHIFT 0 -#define AEQ_CTRL_0_DMA_ATTR_SHIFT 12 -#define AEQ_CTRL_0_PCI_INTF_IDX_SHIFT 20 -#define AEQ_CTRL_0_INTR_MODE_SHIFT 31 - -#define AEQ_CTRL_0_INTR_IDX_MASK 0x3FFU -#define AEQ_CTRL_0_DMA_ATTR_MASK 0x3FU -#define AEQ_CTRL_0_PCI_INTF_IDX_MASK 0x7U -#define AEQ_CTRL_0_INTR_MODE_MASK 0x1U - -#define AEQ_CTRL_0_SET(val, member) \ - (((val) & AEQ_CTRL_0_##member##_MASK) << \ - AEQ_CTRL_0_##member##_SHIFT) - -#define AEQ_CTRL_0_CLEAR(val, member) \ - ((val) & (~(AEQ_CTRL_0_##member##_MASK << \ - AEQ_CTRL_0_##member##_SHIFT))) - -#define AEQ_CTRL_1_LEN_SHIFT 0 -#define AEQ_CTRL_1_ELEM_SIZE_SHIFT 24 -#define AEQ_CTRL_1_PAGE_SIZE_SHIFT 28 - -#define AEQ_CTRL_1_LEN_MASK 0x1FFFFFU -#define AEQ_CTRL_1_ELEM_SIZE_MASK 0x3U -#define AEQ_CTRL_1_PAGE_SIZE_MASK 0xFU - -#define AEQ_CTRL_1_SET(val, member) \ - (((val) & AEQ_CTRL_1_##member##_MASK) << \ - AEQ_CTRL_1_##member##_SHIFT) - -#define AEQ_CTRL_1_CLEAR(val, member) \ - ((val) & (~(AEQ_CTRL_1_##member##_MASK << \ - AEQ_CTRL_1_##member##_SHIFT))) - -#define SPHW_EQ_PROD_IDX_MASK 0xFFFFF -#define SPHW_TASK_PROCESS_EQE_LIMIT 1024 -#define SPHW_EQ_UPDATE_CI_STEP 64 - -static uint g_aeq_len = SPHW_DEFAULT_AEQ_LEN; -module_param(g_aeq_len, uint, 0444); -MODULE_PARM_DESC(g_aeq_len, - "aeq depth, valid range is " __stringify(SPHW_MIN_AEQ_LEN) - " - " __stringify(SPHW_MAX_AEQ_LEN)); - -static uint g_ceq_len = SPHW_DEFAULT_CEQ_LEN; -module_param(g_ceq_len, uint, 0444); -MODULE_PARM_DESC(g_ceq_len, - "ceq depth, valid range is " __stringify(SPHW_MIN_CEQ_LEN) - " - " __stringify(SPHW_MAX_CEQ_LEN)); - -static uint g_num_ceqe_in_tasklet = SPHW_TASK_PROCESS_EQE_LIMIT; -module_param(g_num_ceqe_in_tasklet, uint, 0444); -MODULE_PARM_DESC(g_num_ceqe_in_tasklet, - "The max number of ceqe can be processed in tasklet, default = 1024"); - -#define CEQ_CTRL_0_INTR_IDX_SHIFT 0 -#define CEQ_CTRL_0_DMA_ATTR_SHIFT 12 -#define CEQ_CTRL_0_LIMIT_KICK_SHIFT 20 -#define CEQ_CTRL_0_PCI_INTF_IDX_SHIFT 24 -#define CEQ_CTRL_0_PAGE_SIZE_SHIFT 27 -#define CEQ_CTRL_0_INTR_MODE_SHIFT 31 - -#define CEQ_CTRL_0_INTR_IDX_MASK 0x3FFU -#define CEQ_CTRL_0_DMA_ATTR_MASK 0x3FU -#define CEQ_CTRL_0_LIMIT_KICK_MASK 0xFU -#define CEQ_CTRL_0_PCI_INTF_IDX_MASK 0x3U -#define CEQ_CTRL_0_PAGE_SIZE_MASK 0xF -#define CEQ_CTRL_0_INTR_MODE_MASK 0x1U - -#define CEQ_CTRL_0_SET(val, member) \ - (((val) & CEQ_CTRL_0_##member##_MASK) << \ - CEQ_CTRL_0_##member##_SHIFT) - -#define CEQ_CTRL_1_LEN_SHIFT 0 -#define CEQ_CTRL_1_GLB_FUNC_ID_SHIFT 20 - -#define CEQ_CTRL_1_LEN_MASK 0xFFFFFU -#define CEQ_CTRL_1_GLB_FUNC_ID_MASK 0xFFFU - -#define CEQ_CTRL_1_SET(val, member) \ - (((val) & CEQ_CTRL_1_##member##_MASK) << \ - CEQ_CTRL_1_##member##_SHIFT) - -#define EQ_ELEM_DESC_TYPE_SHIFT 0 -#define EQ_ELEM_DESC_SRC_SHIFT 7 -#define EQ_ELEM_DESC_SIZE_SHIFT 8 -#define EQ_ELEM_DESC_WRAPPED_SHIFT 31 - -#define EQ_ELEM_DESC_TYPE_MASK 0x7FU -#define EQ_ELEM_DESC_SRC_MASK 0x1U -#define EQ_ELEM_DESC_SIZE_MASK 0xFFU -#define EQ_ELEM_DESC_WRAPPED_MASK 0x1U - -#define EQ_ELEM_DESC_GET(val, member) \ - (((val) >> EQ_ELEM_DESC_##member##_SHIFT) & \ - EQ_ELEM_DESC_##member##_MASK) - -#define EQ_CONS_IDX_CONS_IDX_SHIFT 0 -#define EQ_CONS_IDX_INT_ARMED_SHIFT 31 - -#define EQ_CONS_IDX_CONS_IDX_MASK 0x1FFFFFU -#define EQ_CONS_IDX_INT_ARMED_MASK 0x1U - -#define EQ_CONS_IDX_SET(val, member) \ - (((val) & EQ_CONS_IDX_##member##_MASK) << \ - EQ_CONS_IDX_##member##_SHIFT) - -#define EQ_CONS_IDX_CLEAR(val, member) \ - ((val) & (~(EQ_CONS_IDX_##member##_MASK << \ - EQ_CONS_IDX_##member##_SHIFT))) - -#define EQ_CI_SIMPLE_INDIR_CI_SHIFT 0 -#define EQ_CI_SIMPLE_INDIR_ARMED_SHIFT 21 -#define EQ_CI_SIMPLE_INDIR_AEQ_IDX_SHIFT 30 -#define EQ_CI_SIMPLE_INDIR_CEQ_IDX_SHIFT 24 - -#define EQ_CI_SIMPLE_INDIR_CI_MASK 0x1FFFFFU -#define EQ_CI_SIMPLE_INDIR_ARMED_MASK 0x1U -#define EQ_CI_SIMPLE_INDIR_AEQ_IDX_MASK 0x3U -#define EQ_CI_SIMPLE_INDIR_CEQ_IDX_MASK 0xFFU - -#define EQ_CI_SIMPLE_INDIR_SET(val, member) \ - (((val) & EQ_CI_SIMPLE_INDIR_##member##_MASK) << \ - EQ_CI_SIMPLE_INDIR_##member##_SHIFT) - -#define EQ_CI_SIMPLE_INDIR_CLEAR(val, member) \ - ((val) & (~(EQ_CI_SIMPLE_INDIR_##member##_MASK << \ - EQ_CI_SIMPLE_INDIR_##member##_SHIFT))) - -#define EQ_WRAPPED(eq) ((u32)(eq)->wrapped << EQ_VALID_SHIFT) - -#define EQ_CONS_IDX(eq) ((eq)->cons_idx | \ - ((u32)(eq)->wrapped << EQ_WRAPPED_SHIFT)) - -#define EQ_CONS_IDX_REG_ADDR(eq) \ - (((eq)->type == SPHW_AEQ) ? \ - SPHW_CSR_AEQ_CONS_IDX_ADDR : \ - SPHW_CSR_CEQ_CONS_IDX_ADDR) -#define EQ_CI_SIMPLE_INDIR_REG_ADDR(eq) \ - (((eq)->type == SPHW_AEQ) ? \ - SPHW_CSR_AEQ_CI_SIMPLE_INDIR_ADDR : \ - SPHW_CSR_CEQ_CI_SIMPLE_INDIR_ADDR) - -#define EQ_PROD_IDX_REG_ADDR(eq) \ - (((eq)->type == SPHW_AEQ) ? \ - SPHW_CSR_AEQ_PROD_IDX_ADDR : \ - SPHW_CSR_CEQ_PROD_IDX_ADDR) - -#define SPHW_EQ_HI_PHYS_ADDR_REG(type, pg_num) \ - ((u32)((type == SPHW_AEQ) ? \ - SPHW_AEQ_HI_PHYS_ADDR_REG(pg_num) : \ - SPHW_CEQ_HI_PHYS_ADDR_REG(pg_num))) - -#define SPHW_EQ_LO_PHYS_ADDR_REG(type, pg_num) \ - ((u32)((type == SPHW_AEQ) ? \ - SPHW_AEQ_LO_PHYS_ADDR_REG(pg_num) : \ - SPHW_CEQ_LO_PHYS_ADDR_REG(pg_num))) - -#define GET_EQ_NUM_PAGES(eq, size) \ - ((u16)(ALIGN((u32)((eq)->eq_len * (eq)->elem_size), \ - (size)) / (size))) - -#define SPHW_EQ_MAX_PAGES(eq) \ - ((eq)->type == SPHW_AEQ ? SPHW_AEQ_MAX_PAGES : \ - SPHW_CEQ_MAX_PAGES) - -#define GET_EQ_NUM_ELEMS(eq, pg_size) ((pg_size) / (u32)(eq)->elem_size) - -#define GET_EQ_ELEMENT(eq, idx) \ - (((u8 *)(eq)->eq_pages[(idx) / (eq)->num_elem_in_pg].align_vaddr) + \ - (u32)(((idx) & ((eq)->num_elem_in_pg - 1)) * (eq)->elem_size)) - -#define GET_AEQ_ELEM(eq, idx) \ - ((struct sphw_aeq_elem *)GET_EQ_ELEMENT((eq), (idx))) - -#define GET_CEQ_ELEM(eq, idx) ((u32 *)GET_EQ_ELEMENT((eq), (idx))) - -#define GET_CURR_AEQ_ELEM(eq) GET_AEQ_ELEM((eq), (eq)->cons_idx) - -#define GET_CURR_CEQ_ELEM(eq) GET_CEQ_ELEM((eq), (eq)->cons_idx) - -#define PAGE_IN_4K(page_size) ((page_size) >> 12) -#define EQ_SET_HW_PAGE_SIZE_VAL(eq) \ - ((u32)ilog2(PAGE_IN_4K((eq)->page_size))) - -#define ELEMENT_SIZE_IN_32B(eq) (((eq)->elem_size) >> 5) -#define EQ_SET_HW_ELEM_SIZE_VAL(eq) ((u32)ilog2(ELEMENT_SIZE_IN_32B(eq))) - -#define AEQ_DMA_ATTR_DEFAULT 0 -#define CEQ_DMA_ATTR_DEFAULT 0 - -#define CEQ_LMT_KICK_DEFAULT 0 - -#define EQ_MSIX_RESEND_TIMER_CLEAR 1 - -#define EQ_WRAPPED_SHIFT 20 - -#define EQ_VALID_SHIFT 31 - -#define CEQE_TYPE_SHIFT 23 -#define CEQE_TYPE_MASK 0x7 - -#define CEQE_TYPE(type) (((type) >> CEQE_TYPE_SHIFT) & \ - CEQE_TYPE_MASK) - -#define CEQE_DATA_MASK 0x3FFFFFF -#define CEQE_DATA(data) ((data) & CEQE_DATA_MASK) - -#define aeq_to_aeqs(eq) \ - container_of((eq) - (eq)->q_id, struct sphw_aeqs, aeq[0]) - -#define ceq_to_ceqs(eq) \ - container_of((eq) - (eq)->q_id, struct sphw_ceqs, ceq[0]) - -static irqreturn_t ceq_interrupt(int irq, void *data); -static irqreturn_t aeq_interrupt(int irq, void *data); - -static void ceq_tasklet(ulong eq_tasklet); - -/** - * sphw_aeq_register_hw_cb - register aeq callback for specific event - * @hwdev: the pointer to hw device - * @event: event for the handler - * @hw_cb: callback function - **/ -int sphw_aeq_register_hw_cb(void *hwdev, enum sphw_aeq_type event, sphw_aeq_hwe_cb hwe_cb) -{ - struct sphw_aeqs *aeqs = NULL; - - if (!hwdev || !hwe_cb || event >= SPHW_MAX_AEQ_EVENTS) - return -EINVAL; - - aeqs = ((struct sphw_hwdev *)hwdev)->aeqs; - - aeqs->aeq_hwe_cb[event] = hwe_cb; - - set_bit(SPHW_AEQ_HW_CB_REG, &aeqs->aeq_hw_cb_state[event]); - - return 0; -} - -/** - * sphw_aeq_unregister_hw_cb - unregister the aeq callback for specific event - * @hwdev: the pointer to hw device - * @event: event for the handler - **/ -void sphw_aeq_unregister_hw_cb(void *hwdev, enum sphw_aeq_type event) -{ - struct sphw_aeqs *aeqs = NULL; - - if (!hwdev || event >= SPHW_MAX_AEQ_EVENTS) - return; - - aeqs = ((struct sphw_hwdev *)hwdev)->aeqs; - - clear_bit(SPHW_AEQ_HW_CB_REG, &aeqs->aeq_hw_cb_state[event]); - - while (test_bit(SPHW_AEQ_HW_CB_RUNNING, - &aeqs->aeq_hw_cb_state[event])) - usleep_range(EQ_USLEEP_LOW_BOUND, EQ_USLEEP_HIG_BOUND); - - aeqs->aeq_hwe_cb[event] = NULL; -} - -/** - * sphw_aeq_register_swe_cb - register aeq callback for sw event - * @hwdev: the pointer to hw device - * @event: soft event for the handler - * @sw_cb: callback function - **/ -int sphw_aeq_register_swe_cb(void *hwdev, enum sphw_aeq_sw_type event, sphw_aeq_swe_cb aeq_swe_cb) -{ - struct sphw_aeqs *aeqs = NULL; - - if (!hwdev || !aeq_swe_cb || event >= SPHW_MAX_AEQ_SW_EVENTS) - return -EINVAL; - - aeqs = ((struct sphw_hwdev *)hwdev)->aeqs; - - aeqs->aeq_swe_cb[event] = aeq_swe_cb; - - set_bit(SPHW_AEQ_SW_CB_REG, &aeqs->aeq_sw_cb_state[event]); - - return 0; -} - -/** - * sphw_aeq_unregister_swe_cb - unregister the aeq callback for sw event - * @hwdev: the pointer to hw device - * @event: soft event for the handler - **/ -void sphw_aeq_unregister_swe_cb(void *hwdev, enum sphw_aeq_sw_type event) -{ - struct sphw_aeqs *aeqs = NULL; - - if (!hwdev || event >= SPHW_MAX_AEQ_SW_EVENTS) - return; - - aeqs = ((struct sphw_hwdev *)hwdev)->aeqs; - - clear_bit(SPHW_AEQ_SW_CB_REG, &aeqs->aeq_sw_cb_state[event]); - - while (test_bit(SPHW_AEQ_SW_CB_RUNNING, - &aeqs->aeq_sw_cb_state[event])) - usleep_range(EQ_USLEEP_LOW_BOUND, EQ_USLEEP_HIG_BOUND); - - aeqs->aeq_swe_cb[event] = NULL; -} - -/** - * sphw_ceq_register_cb - register ceq callback for specific event - * @hwdev: the pointer to hw device - * @event: event for the handler - * @ceq_cb: callback function - **/ -int sphw_ceq_register_cb(void *hwdev, enum sphw_ceq_event event, sphw_ceq_event_cb callback) -{ - struct sphw_ceqs *ceqs = NULL; - - if (!hwdev || event >= SPHW_MAX_CEQ_EVENTS) - return -EINVAL; - - ceqs = ((struct sphw_hwdev *)hwdev)->ceqs; - - ceqs->ceq_cb[event] = callback; - - set_bit(SPHW_CEQ_CB_REG, &ceqs->ceq_cb_state[event]); - - return 0; -} - -/** - * sphw_ceq_unregister_cb - unregister ceq callback for specific event - * @hwdev: the pointer to hw device - * @event: event for the handler - **/ -void sphw_ceq_unregister_cb(void *hwdev, enum sphw_ceq_event event) -{ - struct sphw_ceqs *ceqs = NULL; - - if (!hwdev || event >= SPHW_MAX_CEQ_EVENTS) - return; - - ceqs = ((struct sphw_hwdev *)hwdev)->ceqs; - - clear_bit(SPHW_CEQ_CB_REG, &ceqs->ceq_cb_state[event]); - - while (test_bit(SPHW_CEQ_CB_RUNNING, &ceqs->ceq_cb_state[event])) - usleep_range(EQ_USLEEP_LOW_BOUND, EQ_USLEEP_HIG_BOUND); - - ceqs->ceq_cb[event] = NULL; -} - -/** - * set_eq_cons_idx - write the cons idx to the hw - * @eq: The event queue to update the cons idx for - * @cons idx: consumer index value - **/ -static void set_eq_cons_idx(struct sphw_eq *eq, u32 arm_state) -{ - u32 eq_wrap_ci, val; - u32 addr = EQ_CI_SIMPLE_INDIR_REG_ADDR(eq); - - eq_wrap_ci = EQ_CONS_IDX(eq); - val = EQ_CI_SIMPLE_INDIR_SET(arm_state, ARMED); - if (eq->type == SPHW_AEQ) { - val = val | - EQ_CI_SIMPLE_INDIR_SET(eq_wrap_ci, CI) | - EQ_CI_SIMPLE_INDIR_SET(eq->q_id, AEQ_IDX); - } else { - val = val | - EQ_CI_SIMPLE_INDIR_SET(eq_wrap_ci, CI) | - EQ_CI_SIMPLE_INDIR_SET(eq->q_id, CEQ_IDX); - } - - sphw_hwif_write_reg(eq->hwdev->hwif, addr, val); -} - -/** - * ceq_event_handler - handle for the ceq events - * @ceqs: ceqs part of the chip - * @ceqe: ceq element of the event - **/ -static void ceq_event_handler(struct sphw_ceqs *ceqs, u32 ceqe) -{ - struct sphw_hwdev *hwdev = ceqs->hwdev; - enum sphw_ceq_event event = CEQE_TYPE(ceqe); - u32 ceqe_data = CEQE_DATA(ceqe); - - if (event >= SPHW_MAX_CEQ_EVENTS) { - sdk_err(hwdev->dev_hdl, "Ceq unknown event:%d, ceqe date: 0x%x\n", - event, ceqe_data); - return; - } - - set_bit(SPHW_CEQ_CB_RUNNING, &ceqs->ceq_cb_state[event]); - - if (ceqs->ceq_cb[event] && - test_bit(SPHW_CEQ_CB_REG, &ceqs->ceq_cb_state[event])) - ceqs->ceq_cb[event](hwdev, ceqe_data); - - clear_bit(SPHW_CEQ_CB_RUNNING, &ceqs->ceq_cb_state[event]); -} - -static void aeq_elem_handler(struct sphw_eq *eq, u32 aeqe_desc) -{ - struct sphw_aeqs *aeqs = aeq_to_aeqs(eq); - struct sphw_aeq_elem *aeqe_pos; - enum sphw_aeq_type event; - enum sphw_aeq_sw_type sw_type; - u32 sw_event; - u8 data[SPHW_AEQE_DATA_SIZE], size; - - aeqe_pos = GET_CURR_AEQ_ELEM(eq); - - event = EQ_ELEM_DESC_GET(aeqe_desc, TYPE); - if (EQ_ELEM_DESC_GET(aeqe_desc, SRC)) { - sw_event = event; - sw_type = sw_event >= SPHW_NIC_FATAL_ERROR_MAX ? - SPHW_STATEFULL_EVENT : - SPHW_STATELESS_EVENT; - /* SW event uses only the first 8B */ - memcpy(data, aeqe_pos->aeqe_data, SPHW_AEQE_DATA_SIZE); - sphw_be32_to_cpu(data, SPHW_AEQE_DATA_SIZE); - set_bit(SPHW_AEQ_SW_CB_RUNNING, - &aeqs->aeq_sw_cb_state[sw_type]); - if (aeqs->aeq_swe_cb[sw_type] && - test_bit(SPHW_AEQ_SW_CB_REG, - &aeqs->aeq_sw_cb_state[sw_type])) - aeqs->aeq_swe_cb[sw_type](aeqs->hwdev, event, data); - - clear_bit(SPHW_AEQ_SW_CB_RUNNING, - &aeqs->aeq_sw_cb_state[sw_type]); - return; - } - - if (event < SPHW_MAX_AEQ_EVENTS) { - memcpy(data, aeqe_pos->aeqe_data, SPHW_AEQE_DATA_SIZE); - sphw_be32_to_cpu(data, SPHW_AEQE_DATA_SIZE); - - size = EQ_ELEM_DESC_GET(aeqe_desc, SIZE); - set_bit(SPHW_AEQ_HW_CB_RUNNING, - &aeqs->aeq_hw_cb_state[event]); - if (aeqs->aeq_hwe_cb[event] && - test_bit(SPHW_AEQ_HW_CB_REG, - &aeqs->aeq_hw_cb_state[event])) - aeqs->aeq_hwe_cb[event](aeqs->hwdev, data, size); - clear_bit(SPHW_AEQ_HW_CB_RUNNING, - &aeqs->aeq_hw_cb_state[event]); - return; - } - sdk_warn(eq->hwdev->dev_hdl, "Unknown aeq hw event %d\n", event); -} - -/** - * aeq_irq_handler - handler for the aeq event - * @eq: the async event queue of the event - **/ -static bool aeq_irq_handler(struct sphw_eq *eq) -{ - struct sphw_aeq_elem *aeqe_pos = NULL; - u32 aeqe_desc; - u32 i, eqe_cnt = 0; - - for (i = 0; i < SPHW_TASK_PROCESS_EQE_LIMIT; i++) { - aeqe_pos = GET_CURR_AEQ_ELEM(eq); - - /* Data in HW is in Big endian Format */ - aeqe_desc = be32_to_cpu(aeqe_pos->desc); - - /* HW updates wrapped bit, when it adds eq element event */ - if (EQ_ELEM_DESC_GET(aeqe_desc, WRAPPED) == eq->wrapped) - return false; - - aeq_elem_handler(eq, aeqe_desc); - - eq->cons_idx++; - - if (eq->cons_idx == eq->eq_len) { - eq->cons_idx = 0; - eq->wrapped = !eq->wrapped; - } - - if (++eqe_cnt >= SPHW_EQ_UPDATE_CI_STEP) { - eqe_cnt = 0; - set_eq_cons_idx(eq, SPHW_EQ_NOT_ARMED); - } - } - - return true; -} - -/** - * ceq_irq_handler - handler for the ceq event - * @eq: the completion event queue of the event - **/ -static bool ceq_irq_handler(struct sphw_eq *eq) -{ - struct sphw_ceqs *ceqs = ceq_to_ceqs(eq); - u32 ceqe, eqe_cnt = 0; - u32 i; - - for (i = 0; i < g_num_ceqe_in_tasklet; i++) { - ceqe = *(GET_CURR_CEQ_ELEM(eq)); - ceqe = be32_to_cpu(ceqe); - - /* HW updates wrapped bit, when it adds eq element event */ - if (EQ_ELEM_DESC_GET(ceqe, WRAPPED) == eq->wrapped) - return false; - - ceq_event_handler(ceqs, ceqe); - - eq->cons_idx++; - - if (eq->cons_idx == eq->eq_len) { - eq->cons_idx = 0; - eq->wrapped = !eq->wrapped; - } - - if (++eqe_cnt >= SPHW_EQ_UPDATE_CI_STEP) { - eqe_cnt = 0; - set_eq_cons_idx(eq, SPHW_EQ_NOT_ARMED); - } - } - - return true; -} - -static void reschedule_eq_handler(struct sphw_eq *eq) -{ - if (eq->type == SPHW_AEQ) { - struct sphw_aeqs *aeqs = aeq_to_aeqs(eq); - struct workqueue_struct *workq = aeqs->workq; - struct sphw_eq_work *aeq_work = &eq->aeq_work; - - queue_work_on(sphw_get_work_cpu_affinity(eq->hwdev, WORK_TYPE_AEQ), - workq, &aeq_work->work); - } else { - tasklet_schedule(&eq->ceq_tasklet); - } -} - -/** - * eq_irq_handler - handler for the eq event - * @data: the event queue of the event - **/ -static bool eq_irq_handler(void *data) -{ - struct sphw_eq *eq = (struct sphw_eq *)data; - bool uncompleted = false; - - if (eq->type == SPHW_AEQ) - uncompleted = aeq_irq_handler(eq); - else - uncompleted = ceq_irq_handler(eq); - - set_eq_cons_idx(eq, uncompleted ? SPHW_EQ_NOT_ARMED : - SPHW_EQ_ARMED); - - return uncompleted; -} - -/** - * eq_irq_work - eq work for the event - * @work: the work that is associated with the eq - **/ -static void eq_irq_work(struct work_struct *work) -{ - struct sphw_eq_work *aeq_work = - container_of(work, struct sphw_eq_work, work); - - if (eq_irq_handler(aeq_work->data)) - reschedule_eq_handler(aeq_work->data); -} - -/** - * aeq_interrupt - aeq interrupt handler - * @irq: irq number - * @data: the async event queue of the event - **/ -static irqreturn_t aeq_interrupt(int irq, void *data) -{ - struct sphw_eq *aeq = (struct sphw_eq *)data; - struct sphw_hwdev *hwdev = aeq->hwdev; - struct sphw_aeqs *aeqs = aeq_to_aeqs(aeq); - struct workqueue_struct *workq = aeqs->workq; - struct sphw_eq_work *aeq_work = NULL; - - /* clear resend timer cnt register */ - sphw_misx_intr_clear_resend_bit(hwdev, aeq->eq_irq.msix_entry_idx, - EQ_MSIX_RESEND_TIMER_CLEAR); - - aeq_work = &aeq->aeq_work; - aeq_work->data = aeq; - - queue_work_on(sphw_get_work_cpu_affinity(hwdev, WORK_TYPE_AEQ), - workq, &aeq_work->work); - - return IRQ_HANDLED; -} - -/** - * ceq_tasklet - ceq tasklet for the event - * @ceq_data: data that will be used by the tasklet(ceq) - **/ -static void ceq_tasklet(ulong ceq_data) -{ - struct sphw_ceq_tasklet_data *ceq_tasklet_data = - (struct sphw_ceq_tasklet_data *)ceq_data; - struct sphw_eq *eq = (struct sphw_eq *)ceq_tasklet_data->data; - - eq->soft_intr_jif = jiffies; - - if (eq_irq_handler(ceq_tasklet_data->data)) - reschedule_eq_handler(ceq_tasklet_data->data); -} - -/** - * ceq_interrupt - ceq interrupt handler - * @irq: irq number - * @data: the completion event queue of the event - **/ -static irqreturn_t ceq_interrupt(int irq, void *data) -{ - struct sphw_eq *ceq = (struct sphw_eq *)data; - struct sphw_ceq_tasklet_data *ceq_tasklet_data = NULL; - - ceq->hard_intr_jif = jiffies; - - /* clear resend timer counters */ - sphw_misx_intr_clear_resend_bit(ceq->hwdev, ceq->eq_irq.msix_entry_idx, - EQ_MSIX_RESEND_TIMER_CLEAR); - - ceq_tasklet_data = &ceq->ceq_tasklet_data; - ceq_tasklet_data->data = data; - tasklet_schedule(&ceq->ceq_tasklet); - - return IRQ_HANDLED; -} - -/** - * set_eq_ctrls - setting eq's ctrls registers - * @eq: the event queue for setting - **/ -static int set_eq_ctrls(struct sphw_eq *eq) -{ - enum sphw_eq_type type = eq->type; - struct sphw_hwif *hwif = eq->hwdev->hwif; - struct irq_info *eq_irq = &eq->eq_irq; - u32 addr, val, ctrl0, ctrl1, page_size_val, elem_size; - u32 pci_intf_idx = SPHW_PCI_INTF_IDX(hwif); - int err; - - if (type == SPHW_AEQ) { - /* set ctrl0 */ - addr = SPHW_CSR_AEQ_CTRL_0_ADDR; - - val = sphw_hwif_read_reg(hwif, addr); - - val = AEQ_CTRL_0_CLEAR(val, INTR_IDX) & - AEQ_CTRL_0_CLEAR(val, DMA_ATTR) & - AEQ_CTRL_0_CLEAR(val, PCI_INTF_IDX) & - AEQ_CTRL_0_CLEAR(val, INTR_MODE); - - ctrl0 = AEQ_CTRL_0_SET(eq_irq->msix_entry_idx, INTR_IDX) | - AEQ_CTRL_0_SET(AEQ_DMA_ATTR_DEFAULT, DMA_ATTR) | - AEQ_CTRL_0_SET(pci_intf_idx, PCI_INTF_IDX) | - AEQ_CTRL_0_SET(SPHW_INTR_MODE_ARMED, INTR_MODE); - - val |= ctrl0; - - sphw_hwif_write_reg(hwif, addr, val); - - /* set ctrl1 */ - addr = SPHW_CSR_AEQ_CTRL_1_ADDR; - - page_size_val = EQ_SET_HW_PAGE_SIZE_VAL(eq); - elem_size = EQ_SET_HW_ELEM_SIZE_VAL(eq); - - ctrl1 = AEQ_CTRL_1_SET(eq->eq_len, LEN) | - AEQ_CTRL_1_SET(elem_size, ELEM_SIZE) | - AEQ_CTRL_1_SET(page_size_val, PAGE_SIZE); - - sphw_hwif_write_reg(hwif, addr, ctrl1); - - } else { - page_size_val = EQ_SET_HW_PAGE_SIZE_VAL(eq); - ctrl0 = CEQ_CTRL_0_SET(eq_irq->msix_entry_idx, INTR_IDX) | - CEQ_CTRL_0_SET(CEQ_DMA_ATTR_DEFAULT, DMA_ATTR) | - CEQ_CTRL_0_SET(CEQ_LMT_KICK_DEFAULT, LIMIT_KICK) | - CEQ_CTRL_0_SET(pci_intf_idx, PCI_INTF_IDX) | - CEQ_CTRL_0_SET(page_size_val, PAGE_SIZE) | - CEQ_CTRL_0_SET(SPHW_INTR_MODE_ARMED, INTR_MODE); - - ctrl1 = CEQ_CTRL_1_SET(eq->eq_len, LEN); - - /* set ceq ctrl reg through mgmt cpu */ - err = sphw_set_ceq_ctrl_reg(eq->hwdev, eq->q_id, ctrl0, ctrl1); - if (err) - return err; - } - - return 0; -} - -/** - * ceq_elements_init - Initialize all the elements in the ceq - * @eq: the event queue - * @init_val: value to init with it the elements - **/ -static void ceq_elements_init(struct sphw_eq *eq, u32 init_val) -{ - u32 *ceqe = NULL; - u32 i; - - for (i = 0; i < eq->eq_len; i++) { - ceqe = GET_CEQ_ELEM(eq, i); - *(ceqe) = cpu_to_be32(init_val); - } - - wmb(); /* Write the init values */ -} - -/** - * aeq_elements_init - initialize all the elements in the aeq - * @eq: the event queue - * @init_val: value to init with it the elements - **/ -static void aeq_elements_init(struct sphw_eq *eq, u32 init_val) -{ - struct sphw_aeq_elem *aeqe = NULL; - u32 i; - - for (i = 0; i < eq->eq_len; i++) { - aeqe = GET_AEQ_ELEM(eq, i); - aeqe->desc = cpu_to_be32(init_val); - } - - wmb(); /* Write the init values */ -} - -static void eq_elements_init(struct sphw_eq *eq, u32 init_val) -{ - if (eq->type == SPHW_AEQ) - aeq_elements_init(eq, init_val); - else - ceq_elements_init(eq, init_val); -} - -/** - * alloc_eq_pages - allocate the pages for the queue - * @eq: the event queue - **/ -static int alloc_eq_pages(struct sphw_eq *eq) -{ - struct sphw_hwif *hwif = eq->hwdev->hwif; - struct sphw_dma_addr_align *eq_page = NULL; - u32 reg, init_val; - u16 pg_idx, i; - int err; - - eq->eq_pages = kcalloc(eq->num_pages, sizeof(*eq->eq_pages), - GFP_KERNEL); - if (!eq->eq_pages) { - sdk_err(eq->hwdev->dev_hdl, "Failed to alloc eq pages description\n"); - return -ENOMEM; - } - - for (pg_idx = 0; pg_idx < eq->num_pages; pg_idx++) { - eq_page = &eq->eq_pages[pg_idx]; - err = sphw_dma_alloc_coherent_align(eq->hwdev->dev_hdl, eq->page_size, - SPHW_MIN_EQ_PAGE_SIZE, GFP_KERNEL, eq_page); - if (err) { - sdk_err(eq->hwdev->dev_hdl, "Failed to alloc eq page, page index: %hu\n", - pg_idx); - goto dma_alloc_err; - } - - reg = SPHW_EQ_HI_PHYS_ADDR_REG(eq->type, pg_idx); - sphw_hwif_write_reg(hwif, reg, upper_32_bits(eq_page->align_paddr)); - - reg = SPHW_EQ_LO_PHYS_ADDR_REG(eq->type, pg_idx); - sphw_hwif_write_reg(hwif, reg, lower_32_bits(eq_page->align_paddr)); - } - - eq->num_elem_in_pg = GET_EQ_NUM_ELEMS(eq, eq->page_size); - if (eq->num_elem_in_pg & (eq->num_elem_in_pg - 1)) { - sdk_err(eq->hwdev->dev_hdl, "Number element in eq page != power of 2\n"); - err = -EINVAL; - goto dma_alloc_err; - } - init_val = EQ_WRAPPED(eq); - - eq_elements_init(eq, init_val); - - return 0; - -dma_alloc_err: - for (i = 0; i < pg_idx; i++) - sphw_dma_free_coherent_align(eq->hwdev->dev_hdl, &eq->eq_pages[i]); - - kfree(eq->eq_pages); - - return err; -} - -/** - * free_eq_pages - free the pages of the queue - * @eq: the event queue - **/ -static void free_eq_pages(struct sphw_eq *eq) -{ - u16 pg_idx; - - for (pg_idx = 0; pg_idx < eq->num_pages; pg_idx++) - sphw_dma_free_coherent_align(eq->hwdev->dev_hdl, &eq->eq_pages[pg_idx]); - - kfree(eq->eq_pages); -} - -static inline u32 get_page_size(struct sphw_eq *eq) -{ - u32 total_size; - u32 count; - - total_size = ALIGN((eq->eq_len * eq->elem_size), - SPHW_MIN_EQ_PAGE_SIZE); - - if (total_size <= (SPHW_EQ_MAX_PAGES(eq) * SPHW_MIN_EQ_PAGE_SIZE)) - return SPHW_MIN_EQ_PAGE_SIZE; - - count = (u32)(ALIGN((total_size / SPHW_EQ_MAX_PAGES(eq)), - SPHW_MIN_EQ_PAGE_SIZE) / SPHW_MIN_EQ_PAGE_SIZE); - - /* round up to nearest power of two */ - count = 1U << (u8)fls((int)(count - 1)); - - return ((u32)SPHW_MIN_EQ_PAGE_SIZE) * count; -} - -static int request_eq_irq(struct sphw_eq *eq, struct irq_info *entry) -{ - int err = 0; - - if (eq->type == SPHW_AEQ) { - struct sphw_eq_work *aeq_work = &eq->aeq_work; - - INIT_WORK(&aeq_work->work, eq_irq_work); - } else { - tasklet_init(&eq->ceq_tasklet, ceq_tasklet, - (ulong)(&eq->ceq_tasklet_data)); - } - - if (eq->type == SPHW_AEQ) { - snprintf(eq->irq_name, sizeof(eq->irq_name), - "sphw_aeq%u@pci:%s", eq->q_id, - pci_name(eq->hwdev->pcidev_hdl)); - - err = request_irq(entry->irq_id, aeq_interrupt, 0UL, - eq->irq_name, eq); - } else { - snprintf(eq->irq_name, sizeof(eq->irq_name), - "sphw_ceq%u@pci:%s", eq->q_id, - pci_name(eq->hwdev->pcidev_hdl)); - err = request_irq(entry->irq_id, ceq_interrupt, 0UL, - eq->irq_name, eq); - } - - return err; -} - -static void reset_eq(struct sphw_eq *eq) -{ - /* clear eq_len to force eqe drop in hardware */ - if (eq->type == SPHW_AEQ) - sphw_hwif_write_reg(eq->hwdev->hwif, SPHW_CSR_AEQ_CTRL_1_ADDR, 0); - else - sphw_set_ceq_ctrl_reg(eq->hwdev, eq->q_id, 0, 0); - - wmb(); /* clear eq_len before clear prod idx */ - - sphw_hwif_write_reg(eq->hwdev->hwif, EQ_PROD_IDX_REG_ADDR(eq), 0); -} - -/** - * init_eq - initialize eq - * @eq: the event queue - * @hwdev: the pointer to hw device - * @q_id: Queue id number - * @q_len: the number of EQ elements - * @type: the type of the event queue, ceq or aeq - * @entry: msix entry associated with the event queue - * Return: 0 - Success, Negative - failure - **/ -static int init_eq(struct sphw_eq *eq, struct sphw_hwdev *hwdev, u16 q_id, - u32 q_len, enum sphw_eq_type type, struct irq_info *entry) -{ - int err = 0; - - eq->hwdev = hwdev; - eq->q_id = q_id; - eq->type = type; - eq->eq_len = q_len; - - /* Indirect access should set q_id first */ - sphw_hwif_write_reg(hwdev->hwif, SPHW_EQ_INDIR_IDX_ADDR(eq->type), eq->q_id); - wmb(); /* write index before config */ - - reset_eq(eq); - - eq->cons_idx = 0; - eq->wrapped = 0; - - eq->elem_size = (type == SPHW_AEQ) ? SPHW_AEQE_SIZE : SPHW_CEQE_SIZE; - - eq->page_size = get_page_size(eq); - eq->orig_page_size = eq->page_size; - eq->num_pages = GET_EQ_NUM_PAGES(eq, eq->page_size); - if (eq->num_pages > SPHW_EQ_MAX_PAGES(eq)) { - sdk_err(hwdev->dev_hdl, "Number pages: %u too many pages for eq\n", - eq->num_pages); - return -EINVAL; - } - - err = alloc_eq_pages(eq); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to allocate pages for eq\n"); - return err; - } - - eq->eq_irq.msix_entry_idx = entry->msix_entry_idx; - eq->eq_irq.irq_id = entry->irq_id; - - err = set_eq_ctrls(eq); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to set ctrls for eq\n"); - goto init_eq_ctrls_err; - } - - set_eq_cons_idx(eq, SPHW_EQ_ARMED); - - err = request_eq_irq(eq, entry); - if (err) { - sdk_err(hwdev->dev_hdl, - "Failed to request irq for the eq, err: %d\n", err); - goto req_irq_err; - } - - sphw_set_msix_state(hwdev, entry->msix_entry_idx, SPHW_MSIX_DISABLE); - - return 0; - -init_eq_ctrls_err: -req_irq_err: - free_eq_pages(eq); - return err; -} - -/** - * remove_eq - remove eq - * @eq: the event queue - **/ -static void remove_eq(struct sphw_eq *eq) -{ - struct irq_info *entry = &eq->eq_irq; - - sphw_set_msix_state(eq->hwdev, entry->msix_entry_idx, SPHW_MSIX_DISABLE); - synchronize_irq(entry->irq_id); - - free_irq(entry->irq_id, eq); - - /* Indirect access should set q_id first */ - sphw_hwif_write_reg(eq->hwdev->hwif, SPHW_EQ_INDIR_IDX_ADDR(eq->type), eq->q_id); - - wmb(); /* write index before config */ - - if (eq->type == SPHW_AEQ) { - struct sphw_eq_work *aeq_work = &eq->aeq_work; - - cancel_work_sync(&aeq_work->work); - - /* clear eq_len to avoid hw access host memory */ - sphw_hwif_write_reg(eq->hwdev->hwif, SPHW_CSR_AEQ_CTRL_1_ADDR, 0); - } else { - tasklet_kill(&eq->ceq_tasklet); - - sphw_set_ceq_ctrl_reg(eq->hwdev, eq->q_id, 0, 0); - } - - /* update cons_idx to avoid invalid interrupt */ - eq->cons_idx = sphw_hwif_read_reg(eq->hwdev->hwif, EQ_PROD_IDX_REG_ADDR(eq)); - set_eq_cons_idx(eq, SPHW_EQ_NOT_ARMED); - - free_eq_pages(eq); -} - -/** - * sphw_aeqs_init - init all the aeqs - * @hwdev: the pointer to hw device - * @num_aeqs: number of AEQs - * @msix_entries: msix entries associated with the event queues - * Return: 0 - Success, Negative - failure - **/ -int sphw_aeqs_init(struct sphw_hwdev *hwdev, u16 num_aeqs, struct irq_info *msix_entries) -{ - struct sphw_aeqs *aeqs = NULL; - int err; - u16 i, q_id; - - if (!hwdev) - return -EINVAL; - - aeqs = kzalloc(sizeof(*aeqs), GFP_KERNEL); - if (!aeqs) - return -ENOMEM; - - hwdev->aeqs = aeqs; - aeqs->hwdev = hwdev; - aeqs->num_aeqs = num_aeqs; - aeqs->workq = alloc_workqueue(SPHW_EQS_WQ_NAME, WQ_MEM_RECLAIM, SPHW_MAX_AEQS); - if (!aeqs->workq) { - sdk_err(hwdev->dev_hdl, "Failed to initialize aeq workqueue\n"); - err = -ENOMEM; - goto create_work_err; - } - - if (g_aeq_len < SPHW_MIN_AEQ_LEN || g_aeq_len > SPHW_MAX_AEQ_LEN) { - sdk_warn(hwdev->dev_hdl, "Module Parameter g_aeq_len value %u out of range, resetting to %d\n", - g_aeq_len, SPHW_DEFAULT_AEQ_LEN); - g_aeq_len = SPHW_DEFAULT_AEQ_LEN; - } - - for (q_id = 0; q_id < num_aeqs; q_id++) { - err = init_eq(&aeqs->aeq[q_id], hwdev, q_id, g_aeq_len, - SPHW_AEQ, &msix_entries[q_id]); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init aeq %u\n", - q_id); - goto init_aeq_err; - } - } - for (q_id = 0; q_id < num_aeqs; q_id++) - sphw_set_msix_state(hwdev, msix_entries[q_id].msix_entry_idx, SPHW_MSIX_ENABLE); - - return 0; - -init_aeq_err: - for (i = 0; i < q_id; i++) - remove_eq(&aeqs->aeq[i]); - - destroy_workqueue(aeqs->workq); - -create_work_err: - kfree(aeqs); - - return err; -} - -/** - * sphw_aeqs_free - free all the aeqs - * @hwdev: the pointer to hw device - **/ -void sphw_aeqs_free(struct sphw_hwdev *hwdev) -{ - struct sphw_aeqs *aeqs = hwdev->aeqs; - enum sphw_aeq_type aeq_event = SPHW_HW_INTER_INT; - enum sphw_aeq_sw_type sw_aeq_event = SPHW_STATELESS_EVENT; - u16 q_id; - - for (q_id = 0; q_id < aeqs->num_aeqs; q_id++) - remove_eq(&aeqs->aeq[q_id]); - - for (; sw_aeq_event < SPHW_MAX_AEQ_SW_EVENTS; sw_aeq_event++) - sphw_aeq_unregister_swe_cb(hwdev, sw_aeq_event); - - for (; aeq_event < SPHW_MAX_AEQ_EVENTS; aeq_event++) - sphw_aeq_unregister_hw_cb(hwdev, aeq_event); - - destroy_workqueue(aeqs->workq); - - kfree(aeqs); -} - -/** - * sphw_ceqs_init - init all the ceqs - * @hwdev: the pointer to hw device - * @num_ceqs: number of CEQs - * @msix_entries: msix entries associated with the event queues - * Return: 0 - Success, Negative - failure - **/ -int sphw_ceqs_init(struct sphw_hwdev *hwdev, u16 num_ceqs, struct irq_info *msix_entries) -{ - struct sphw_ceqs *ceqs; - int err; - u16 i, q_id; - - ceqs = kzalloc(sizeof(*ceqs), GFP_KERNEL); - if (!ceqs) - return -ENOMEM; - - hwdev->ceqs = ceqs; - - ceqs->hwdev = hwdev; - ceqs->num_ceqs = num_ceqs; - - if (g_ceq_len < SPHW_MIN_CEQ_LEN || g_ceq_len > SPHW_MAX_CEQ_LEN) { - sdk_warn(hwdev->dev_hdl, "Module Parameter g_ceq_len value %u out of range, resetting to %d\n", - g_ceq_len, SPHW_DEFAULT_CEQ_LEN); - g_ceq_len = SPHW_DEFAULT_CEQ_LEN; - } - - if (!g_num_ceqe_in_tasklet) { - sdk_warn(hwdev->dev_hdl, "Module Parameter g_num_ceqe_in_tasklet can not be zero, resetting to %d\n", - SPHW_TASK_PROCESS_EQE_LIMIT); - g_num_ceqe_in_tasklet = SPHW_TASK_PROCESS_EQE_LIMIT; - } - for (q_id = 0; q_id < num_ceqs; q_id++) { - err = init_eq(&ceqs->ceq[q_id], hwdev, q_id, g_ceq_len, - SPHW_CEQ, &msix_entries[q_id]); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init ceq %u\n", - q_id); - goto init_ceq_err; - } - } - for (q_id = 0; q_id < num_ceqs; q_id++) - sphw_set_msix_state(hwdev, msix_entries[q_id].msix_entry_idx, SPHW_MSIX_ENABLE); - - return 0; - -init_ceq_err: - for (i = 0; i < q_id; i++) - remove_eq(&ceqs->ceq[i]); - - kfree(ceqs); - - return err; -} - -/** - * sphw_ceqs_free - free all the ceqs - * @hwdev: the pointer to hw device - **/ -void sphw_ceqs_free(struct sphw_hwdev *hwdev) -{ - struct sphw_ceqs *ceqs = hwdev->ceqs; - enum sphw_ceq_event ceq_event = SPHW_CMDQ; - u16 q_id; - - for (q_id = 0; q_id < ceqs->num_ceqs; q_id++) - remove_eq(&ceqs->ceq[q_id]); - - for (; ceq_event < SPHW_MAX_CEQ_EVENTS; ceq_event++) - sphw_ceq_unregister_cb(hwdev, ceq_event); - - kfree(ceqs); -} - -void sphw_get_ceq_irqs(struct sphw_hwdev *hwdev, struct irq_info *irqs, u16 *num_irqs) -{ - struct sphw_ceqs *ceqs = hwdev->ceqs; - u16 q_id; - - for (q_id = 0; q_id < ceqs->num_ceqs; q_id++) { - irqs[q_id].irq_id = ceqs->ceq[q_id].eq_irq.irq_id; - irqs[q_id].msix_entry_idx = - ceqs->ceq[q_id].eq_irq.msix_entry_idx; - } - - *num_irqs = ceqs->num_ceqs; -} - -void sphw_get_aeq_irqs(struct sphw_hwdev *hwdev, struct irq_info *irqs, u16 *num_irqs) -{ - struct sphw_aeqs *aeqs = hwdev->aeqs; - u16 q_id; - - for (q_id = 0; q_id < aeqs->num_aeqs; q_id++) { - irqs[q_id].irq_id = aeqs->aeq[q_id].eq_irq.irq_id; - irqs[q_id].msix_entry_idx = - aeqs->aeq[q_id].eq_irq.msix_entry_idx; - } - - *num_irqs = aeqs->num_aeqs; -} - -void sphw_dump_aeq_info(struct sphw_hwdev *hwdev) -{ - struct sphw_aeq_elem *aeqe_pos = NULL; - struct sphw_eq *eq = NULL; - u32 addr, ci, pi, ctrl0, idx; - int q_id; - - for (q_id = 0; q_id < hwdev->aeqs->num_aeqs; q_id++) { - eq = &hwdev->aeqs->aeq[q_id]; - /* Indirect access should set q_id first */ - sphw_hwif_write_reg(eq->hwdev->hwif, SPHW_EQ_INDIR_IDX_ADDR(eq->type), eq->q_id); - wmb(); /* write index before config */ - - addr = SPHW_CSR_AEQ_CTRL_0_ADDR; - - ctrl0 = sphw_hwif_read_reg(hwdev->hwif, addr); - - idx = sphw_hwif_read_reg(hwdev->hwif, SPHW_EQ_INDIR_IDX_ADDR(eq->type)); - - addr = EQ_CONS_IDX_REG_ADDR(eq); - ci = sphw_hwif_read_reg(hwdev->hwif, addr); - addr = EQ_PROD_IDX_REG_ADDR(eq); - pi = sphw_hwif_read_reg(hwdev->hwif, addr); - aeqe_pos = GET_CURR_AEQ_ELEM(eq); - sdk_err(hwdev->dev_hdl, "Aeq id: %d, idx: %u, ctrl0: 0x%08x, ci: 0x%08x, pi: 0x%x, work_state: 0x%x, wrap: %u, desc: 0x%x\n", - q_id, idx, ctrl0, ci, pi, work_busy(&eq->aeq_work.work), - eq->wrapped, be32_to_cpu(aeqe_pos->desc)); - } -} - -void sphw_dump_ceq_info(struct sphw_hwdev *hwdev) -{ - struct sphw_eq *eq = NULL; - u32 addr, ci, pi; - int q_id; - - for (q_id = 0; q_id < hwdev->ceqs->num_ceqs; q_id++) { - eq = &hwdev->ceqs->ceq[q_id]; - /* Indirect access should set q_id first */ - sphw_hwif_write_reg(eq->hwdev->hwif, SPHW_EQ_INDIR_IDX_ADDR(eq->type), eq->q_id); - wmb(); /* write index before config */ - - addr = EQ_CONS_IDX_REG_ADDR(eq); - ci = sphw_hwif_read_reg(hwdev->hwif, addr); - addr = EQ_PROD_IDX_REG_ADDR(eq); - pi = sphw_hwif_read_reg(hwdev->hwif, addr); - sdk_err(hwdev->dev_hdl, "Ceq id: %d, ci: 0x%08x, sw_ci: 0x%08x, pi: 0x%x, tasklet_state: 0x%lx, wrap: %u, ceqe: 0x%x\n", - q_id, ci, eq->cons_idx, pi, eq->ceq_tasklet.state, - eq->wrapped, be32_to_cpu(*(GET_CURR_CEQ_ELEM(eq)))); - - sdk_err(hwdev->dev_hdl, "Ceq last response hard interrupt time: %u\n", - jiffies_to_msecs(jiffies - eq->hard_intr_jif)); - sdk_err(hwdev->dev_hdl, "Ceq last response soft interrupt time: %u\n", - jiffies_to_msecs(jiffies - eq->soft_intr_jif)); - } -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_eqs.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_eqs.h deleted file mode 100644 index df25b5a5fdcf..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_eqs.h +++ /dev/null @@ -1,157 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_EQS_H -#define SPHW_EQS_H - -#define SPHW_MAX_AEQS 4 -#define SPHW_MAX_CEQS 32 - -#define SPHW_AEQ_MAX_PAGES 4 -#define SPHW_CEQ_MAX_PAGES 8 - -#define SPHW_AEQE_SIZE 64 -#define SPHW_CEQE_SIZE 4 - -#define SPHW_AEQE_DESC_SIZE 4 -#define SPHW_AEQE_DATA_SIZE \ - (SPHW_AEQE_SIZE - SPHW_AEQE_DESC_SIZE) - -#define SPHW_DEFAULT_AEQ_LEN 4096 -#define SPHW_DEFAULT_CEQ_LEN 8192 - -#define SPHW_MIN_EQ_PAGE_SIZE 0x1000 /* min eq page size 4K Bytes */ -#define SPHW_MAX_EQ_PAGE_SIZE 0x400000 /* max eq page size 4M Bytes */ - -#define SPHW_MIN_AEQ_LEN 64 -#define SPHW_MAX_AEQ_LEN \ - ((SPHW_MAX_EQ_PAGE_SIZE / SPHW_AEQE_SIZE) * SPHW_AEQ_MAX_PAGES) - -#define SPHW_MIN_CEQ_LEN 64 -#define SPHW_MAX_CEQ_LEN \ - ((SPHW_MAX_EQ_PAGE_SIZE / SPHW_CEQE_SIZE) * SPHW_CEQ_MAX_PAGES) -#define SPHW_CEQ_ID_CMDQ 0 - -#define EQ_IRQ_NAME_LEN 64 - -#define EQ_USLEEP_LOW_BOUND 900 -#define EQ_USLEEP_HIG_BOUND 1000 - -enum sphw_eq_type { - SPHW_AEQ, - SPHW_CEQ -}; - -enum sphw_eq_intr_mode { - SPHW_INTR_MODE_ARMED, - SPHW_INTR_MODE_ALWAYS, -}; - -enum sphw_eq_ci_arm_state { - SPHW_EQ_NOT_ARMED, - SPHW_EQ_ARMED, -}; - -struct sphw_eq_work { - struct work_struct work; - void *data; -}; - -struct sphw_ceq_tasklet_data { - void *data; -}; - -struct sphw_eq { - struct sphw_hwdev *hwdev; - u16 q_id; - enum sphw_eq_type type; - u32 page_size; - u32 orig_page_size; - u32 eq_len; - - u32 cons_idx; - u16 wrapped; - - u16 elem_size; - u16 num_pages; - u32 num_elem_in_pg; - - struct irq_info eq_irq; - char irq_name[EQ_IRQ_NAME_LEN]; - - struct sphw_dma_addr_align *eq_pages; - - struct sphw_eq_work aeq_work; - struct tasklet_struct ceq_tasklet; - struct sphw_ceq_tasklet_data ceq_tasklet_data; - - u64 hard_intr_jif; - u64 soft_intr_jif; -}; - -struct sphw_aeq_elem { - u8 aeqe_data[SPHW_AEQE_DATA_SIZE]; - u32 desc; -}; - -enum sphw_aeq_cb_state { - SPHW_AEQ_HW_CB_REG = 0, - SPHW_AEQ_HW_CB_RUNNING, - SPHW_AEQ_SW_CB_REG, - SPHW_AEQ_SW_CB_RUNNING, -}; - -struct sphw_aeqs { - struct sphw_hwdev *hwdev; - - sphw_aeq_hwe_cb aeq_hwe_cb[SPHW_MAX_AEQ_EVENTS]; - sphw_aeq_swe_cb aeq_swe_cb[SPHW_MAX_AEQ_SW_EVENTS]; - unsigned long aeq_hw_cb_state[SPHW_MAX_AEQ_EVENTS]; - unsigned long aeq_sw_cb_state[SPHW_MAX_AEQ_SW_EVENTS]; - - struct sphw_eq aeq[SPHW_MAX_AEQS]; - u16 num_aeqs; - struct workqueue_struct *workq; -}; - -enum sphw_ceq_cb_state { - SPHW_CEQ_CB_REG = 0, - SPHW_CEQ_CB_RUNNING, -}; - -struct sphw_ceqs { - struct sphw_hwdev *hwdev; - - sphw_ceq_event_cb ceq_cb[SPHW_MAX_CEQ_EVENTS]; - void *ceq_data[SPHW_MAX_CEQ_EVENTS]; - unsigned long ceq_cb_state[SPHW_MAX_CEQ_EVENTS]; - - struct sphw_eq ceq[SPHW_MAX_CEQS]; - u16 num_ceqs; -}; - -struct sphw_ceq_info { - u32 q_len; - u32 page_size; - u16 elem_size; - u16 num_pages; - u32 num_elem_in_pg; -}; - -int sphw_aeqs_init(struct sphw_hwdev *hwdev, u16 num_aeqs, struct irq_info *msix_entries); - -void sphw_aeqs_free(struct sphw_hwdev *hwdev); - -int sphw_ceqs_init(struct sphw_hwdev *hwdev, u16 num_ceqs, struct irq_info *msix_entries); - -void sphw_ceqs_free(struct sphw_hwdev *hwdev); - -void sphw_get_ceq_irqs(struct sphw_hwdev *hwdev, struct irq_info *irqs, u16 *num_irqs); - -void sphw_get_aeq_irqs(struct sphw_hwdev *hwdev, struct irq_info *irqs, u16 *num_irqs); - -void sphw_dump_ceq_info(struct sphw_hwdev *hwdev); - -void sphw_dump_aeq_info(struct sphw_hwdev *hwdev); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw.h deleted file mode 100644 index 41945efe86d8..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw.h +++ /dev/null @@ -1,643 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_HW_H -#define SPHW_HW_H - -#include "sphw_comm_cmd.h" -#include "sphw_comm_msg_intf.h" -#include "sphw_crm.h" - -enum sphw_mod_type { - SPHW_MOD_COMM = 0, /* HW communication module */ - SPHW_MOD_L2NIC = 1, /* L2NIC module */ - SPHW_MOD_ROCE = 2, - SPHW_MOD_PLOG = 3, - SPHW_MOD_TOE = 4, - SPHW_MOD_FLR = 5, - SPHW_MOD_FC = 6, - SPHW_MOD_CFGM = 7, /* Configuration module */ - SPHW_MOD_CQM = 8, - SPHW_MOD_VSWITCH = 9, - COMM_MOD_FC = 10, - SPHW_MOD_OVS = 11, - SPHW_MOD_DSW = 12, - SPHW_MOD_MIGRATE = 13, - SPHW_MOD_HILINK = 14, - SPHW_MOD_CRYPT = 15, /* secure crypto module */ - SPHW_MOD_VIO = 16, - SPHW_MOD_DFT = 17, /* DFT */ - SPHW_MOD_HW_MAX = 18, /* hardware max module id */ - /* Software module id, for PF/VF and multi-host */ - SPHW_MOD_SW_FUNC = 19, - SPHW_MOD_IOE = 20, - SPHW_MOD_MAX, -}; - -/* to use 0-level CLA, page size must be: SQ 16B(wqe) * 64k(max_q_depth) */ -#define SPHW_DEFAULT_WQ_PAGE_SIZE 0x100000 -#define SPHW_HW_WQ_PAGE_SIZE 0x1000 -#define SPHW_MAX_WQ_PAGE_SIZE_ORDER 8 - -enum sphw_channel_id { - SPHW_CHANNEL_DEFAULT, - SPHW_CHANNEL_COMM, - SPHW_CHANNEL_NIC, - SPHW_CHANNEL_ROCE, - SPHW_CHANNEL_TOE, - SPHW_CHANNEL_FC, - SPHW_CHANNEL_OVS, - SPHW_CHANNEL_DSW, - SPHW_CHANNEL_MIG, - SPHW_CHANNEL_CRYPT, - - SPHW_CHANNEL_MAX = 32, -}; - -struct sphw_cmd_buf { - void *buf; - dma_addr_t dma_addr; - u16 size; - /* Usage count, USERS DO NOT USE */ - atomic_t ref_cnt; -}; - -enum sphw_aeq_type { - SPHW_HW_INTER_INT = 0, - SPHW_MBX_FROM_FUNC = 1, - SPHW_MSG_FROM_MGMT_CPU = 2, - SPHW_API_RSP = 3, - SPHW_API_CHAIN_STS = 4, - SPHW_MBX_SEND_RSLT = 5, - SPHW_MAX_AEQ_EVENTS -}; - -#define SPHW_NIC_FATAL_ERROR_MAX 0x8U - -enum sphw_aeq_sw_type { - SPHW_STATELESS_EVENT = 0, - SPHW_STATEFULL_EVENT = 1, - SPHW_MAX_AEQ_SW_EVENTS -}; - -typedef void (*sphw_aeq_hwe_cb)(void *handle, u8 *data, u8 size); -typedef u8 (*sphw_aeq_swe_cb)(void *handle, u8 event, u8 *data); - -/** - * @brief sphw_aeq_register_hw_cb - register aeq hardware callback - * @param hwdev: device pointer to hwdev - * @param event: event type - * @param hwe_cb: callback function - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_aeq_register_hw_cb(void *hwdev, enum sphw_aeq_type event, sphw_aeq_hwe_cb hwe_cb); - -/** - * @brief sphw_aeq_unregister_hw_cb - unregister aeq hardware callback - * @param hwdev: device pointer to hwdev - * @param event: event type - **/ -void sphw_aeq_unregister_hw_cb(void *hwdev, enum sphw_aeq_type event); - -/** - * @brief sphw_aeq_register_swe_cb - register aeq soft event callback - * @param hwdev: device pointer to hwdev - * @param event: event type - * @param aeq_swe_cb: callback function - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_aeq_register_swe_cb(void *hwdev, enum sphw_aeq_sw_type event, sphw_aeq_swe_cb aeq_swe_cb); - -/** - * @brief sphw_aeq_unregister_swe_cb - unregister aeq soft event callback - * @param hwdev: device pointer to hwdev - * @param event: event type - **/ -void sphw_aeq_unregister_swe_cb(void *hwdev, enum sphw_aeq_sw_type event); - -enum sphw_ceq_event { - SPHW_NON_L2NIC_SCQ, - SPHW_NON_L2NIC_ECQ, - SPHW_NON_L2NIC_NO_CQ_EQ, - SPHW_CMDQ, - SPHW_L2NIC_SQ, - SPHW_L2NIC_RQ, - SPHW_MAX_CEQ_EVENTS, -}; - -typedef void (*sphw_ceq_event_cb)(void *handle, u32 ceqe_data); - -/** - * @brief sphw_ceq_register_cb - register ceq callback - * @param hwdev: device pointer to hwdev - * @param event: event type - * @param callback: callback function - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_ceq_register_cb(void *hwdev, enum sphw_ceq_event event, sphw_ceq_event_cb callback); -/** - * @brief sphw_ceq_unregister_cb - unregister ceq callback - * @param hwdev: device pointer to hwdev - * @param event: event type - **/ -void sphw_ceq_unregister_cb(void *hwdev, enum sphw_ceq_event event); - -typedef int (*sphw_vf_mbox_cb)(void *handle, void *pri_handle, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size); - -typedef int (*sphw_pf_mbox_cb)(void *handle, void *pri_handle, u16 vf_id, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size); - -typedef int (*sphw_ppf_mbox_cb)(void *handle, void *pri_handle, - u16 pf_idx, u16 vf_id, u16 cmd, - void *buf_in, u16 in_size, void *buf_out, - u16 *out_size); - -typedef int (*sphw_pf_recv_from_ppf_mbox_cb)(void *handle, void *pri_handle, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size); - -/** - * @brief sphw_register_ppf_mbox_cb - ppf register mbox msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param pri_handle: private data will be used by the callback - * @param callback: callback function - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_register_ppf_mbox_cb(void *hwdev, u8 mod, void *pri_handle, sphw_ppf_mbox_cb callback); - -/** - * @brief sphw_register_pf_mbox_cb - pf register mbox msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param pri_handle: private data will be used by the callback - * @param callback: callback function - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_register_pf_mbox_cb(void *hwdev, u8 mod, void *pri_handle, sphw_pf_mbox_cb callback); -/** - * @brief sphw_register_vf_mbox_cb - vf register mbox msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param pri_handle: private data will be used by the callback - * @param callback: callback function - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_register_vf_mbox_cb(void *hwdev, u8 mod, void *pri_handle, sphw_vf_mbox_cb callback); -/** - * @brief sphw_register_ppf_to_pf_mbox_cb - register mbox msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param pri_handle: private data will be used by the callback - * @param callback: callback function - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_register_ppf_to_pf_mbox_cb(void *hwdev, u8 mod, void *pri_handle, - sphw_pf_recv_from_ppf_mbox_cb callback); - -/** - * @brief sphw_unregister_ppf_mbox_cb - ppf unregister mbox msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - **/ -void sphw_unregister_ppf_mbox_cb(void *hwdev, u8 mod); - -/** - * @brief sphw_unregister_pf_mbox_cb - pf register mbox msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - **/ -void sphw_unregister_pf_mbox_cb(void *hwdev, u8 mod); - -/** - * @brief sphw_unregister_vf_mbox_cb - pf register mbox msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - **/ -void sphw_unregister_vf_mbox_cb(void *hwdev, u8 mod); - -/** - * @brief sphw_unregister_ppf_to_pf_mbox_cb - unregister mbox msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - **/ -void sphw_unregister_ppf_to_pf_mbox_cb(void *hwdev, u8 mod); - -typedef void (*sphw_mgmt_msg_cb)(void *hwdev, void *pri_handle, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size); - -/** - * @brief sphw_register_mgmt_msg_cb - register mgmt msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param pri_handle: private data will be used by the callback - * @param callback: callback function - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_register_mgmt_msg_cb(void *hwdev, u8 mod, void *pri_handle, sphw_mgmt_msg_cb callback); - -/** - * @brief sphw_unregister_mgmt_msg_cb - unregister mgmt msg callback - * @param hwdev: device pointer to hwdev - * @param mod: mod type - **/ -void sphw_unregister_mgmt_msg_cb(void *hwdev, u8 mod); - -/** - * @brief sphw_register_service_adapter - register service adapter - * @param hwdev: device pointer to hwdev - * @param service_adapter: service adapter - * @param type: service type - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_register_service_adapter(void *hwdev, void *service_adapter, - enum sphw_service_type type); - -/** - * @brief sphw_unregister_service_adapter - unregister service adapter - * @param hwdev: device pointer to hwdev - * @param type: service type - **/ -void sphw_unregister_service_adapter(void *hwdev, enum sphw_service_type type); - -/** - * @brief sphw_get_service_adapter - get service adapter - * @param hwdev: device pointer to hwdev - * @param type: service type - * @retval non-zero: success - * @retval null: failure - **/ -void *sphw_get_service_adapter(void *hwdev, enum sphw_service_type type); - -/** - * @brief sphw_alloc_db_phy_addr - alloc doorbell & direct wqe pyhsical addr - * @param hwdev: device pointer to hwdev - * @param db_base: pointer to alloc doorbell base address - * @param dwqe_base: pointer to alloc direct base address - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_alloc_db_phy_addr(void *hwdev, u64 *db_base, u64 *dwqe_base); - -/** - * @brief sphw_free_db_phy_addr - free doorbell & direct wqe physical address - * @param hwdev: device pointer to hwdev - * @param db_base: pointer to free doorbell base address - * @param dwqe_base: pointer to free direct base address - **/ -void sphw_free_db_phy_addr(void *hwdev, u64 db_base, u64 dwqe_base); - -/** - * @brief sphw_alloc_db_addr - alloc doorbell & direct wqe - * @param hwdev: device pointer to hwdev - * @param db_base: pointer to alloc doorbell base address - * @param dwqe_base: pointer to alloc direct base address - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_alloc_db_addr(void *hwdev, void __iomem **db_base, void __iomem **dwqe_base); - -/** - * @brief sphw_free_db_addr - free doorbell & direct wqe - * @param hwdev: device pointer to hwdev - * @param db_base: pointer to free doorbell base address - * @param dwqe_base: pointer to free direct base address - **/ -void sphw_free_db_addr(void *hwdev, const void __iomem *db_base, void __iomem *dwqe_base); - -/** - * @brief sphw_alloc_db_phy_addr - alloc physical doorbell & direct wqe - * @param hwdev: device pointer to hwdev - * @param db_base: pointer to alloc doorbell base address - * @param dwqe_base: pointer to alloc direct base address - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_alloc_db_phy_addr(void *hwdev, u64 *db_base, u64 *dwqe_base); - -/** - * @brief sphw_free_db_phy_addr - free physical doorbell & direct wqe - * @param hwdev: device pointer to hwdev - * @param db_base: free doorbell base address - * @param dwqe_base: free direct base address - **/ - -void sphw_free_db_phy_addr(void *hwdev, u64 db_base, u64 dwqe_base); - -/** - * @brief sphw_set_root_ctxt - set root context - * @param hwdev: device pointer to hwdev - * @param rq_depth: rq depth - * @param sq_depth: sq depth - * @param rx_buf_sz: rx buffer size - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_set_root_ctxt(void *hwdev, u32 rq_depth, u32 sq_depth, int rx_buf_sz, u16 channel); - -/** - * @brief sphw_clean_root_ctxt - clean root context - * @param hwdev: device pointer to hwdev - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - **/ -int sphw_clean_root_ctxt(void *hwdev, u16 channel); - -/** - * @brief sphw_alloc_cmd_buf - alloc cmd buffer - * @param hwdev: device pointer to hwdev - * @retval non-zero: success - * @retval null: failure - **/ -struct sphw_cmd_buf *sphw_alloc_cmd_buf(void *hwdev); - -/** - * @brief sphw_free_cmd_buf - free cmd buffer - * @param hwdev: device pointer to hwdev - * @param cmd_buf: cmd buffer to free - **/ -void sphw_free_cmd_buf(void *hwdev, struct sphw_cmd_buf *cmd_buf); - -/** - * @brief sphw_dbg_get_hw_stats - get hardware stats - * @param hwdev: device pointer to hwdev - * @param hw_stats: pointer to memory caller to alloc - * @param out_size: out size - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_dbg_get_hw_stats(const void *hwdev, u8 *hw_stats, u16 *out_size); - -/** - * @brief sphw_dbg_clear_hw_stats - clear hardware stats - * @param hwdev: device pointer to hwdev - * @retval clear hardware size - */ -u16 sphw_dbg_clear_hw_stats(void *hwdev); - -/** - * @brief sphw_get_chip_fault_stats - get chip fault stats - * @param hwdev: device pointer to hwdev - * @param chip_fault_stats: pointer to memory caller to alloc - * @param offset: offset - */ -void sphw_get_chip_fault_stats(const void *hwdev, u8 *chip_fault_stats, u32 offset); - -/** - * @brief sphw_msg_to_mgmt_sync - msg to management cpu - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param cmd: cmd - * @param buf_in: message buffer in - * @param in_size: in buffer size - * @param buf_out: message buffer out - * @param out_size: out buffer size - * @param timeout: timeout - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_msg_to_mgmt_sync(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, void *buf_out, - u16 *out_size, u32 timeout, u16 channel); - -/** - * @brief sphw_msg_to_mgmt_async - msg to management cpu async - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param cmd: cmd - * @param buf_in: message buffer in - * @param in_size: in buffer size - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - * - * The function does not sleep inside, allowing use in irq context - */ -int sphw_msg_to_mgmt_async(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, u16 channel); - -/** - * @brief sphw_msg_to_mgmt_no_ack - msg to management cpu don't need no ack - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param cmd: cmd - * @param buf_in: message buffer in - * @param in_size: in buffer size - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - * - * The function will sleep inside, and it is not allowed to be used in - * interrupt context - */ -int sphw_msg_to_mgmt_no_ack(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, u16 channel); - -int sphw_msg_to_mgmt_api_chain_async(void *hwdev, u8 mod, u16 cmd, const void *buf_in, u16 in_size); - -int sphw_msg_to_mgmt_api_chain_sync(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u32 timeout); - -/** - * @brief sphw_mbox_to_pf - vf mbox message to pf - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param cmd: cmd - * @param buf_in: message buffer in - * @param in_size: in buffer size - * @param buf_out: message buffer out - * @param out_size: out buffer size - * @param timeout: timeout - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_mbox_to_pf(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, void *buf_out, - u16 *out_size, u32 timeout, u16 channel); - -/** - * @brief sphw_mbox_to_vf - mbox message to vf - * @param hwdev: device pointer to hwdev - * @param vf_id: vf index - * @param mod: mod type - * @param cmd: cmd - * @param buf_in: message buffer in - * @param in_size: in buffer size - * @param buf_out: message buffer out - * @param out_size: out buffer size - * @param timeout: timeout - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_mbox_to_vf(void *hwdev, u16 vf_id, u8 mod, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, u32 timeout, u16 channel); - -/** - * @brief sphw_cmdq_async - cmdq asynchronous message - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param cmd: cmd - * @param buf_in: message buffer in - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_cmdq_async(void *hwdev, u8 mod, u8 cmd, struct sphw_cmd_buf *buf_in, u16 channel); - -/** - * @brief sphw_cmdq_direct_resp - cmdq direct message response - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param cmd: cmd - * @param buf_in: message buffer in - * @param out_param: message out - * @param timeout: timeout - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_cmdq_direct_resp(void *hwdev, u8 mod, u8 cmd, struct sphw_cmd_buf *buf_in, - u64 *out_param, u32 timeout, u16 channel); - -/** - * @brief sphw_cmdq_detail_resp - cmdq detail message response - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param cmd: cmd - * @param buf_in: message buffer in - * @param buf_out: message buffer out - * @param out_param: inline output data - * @param timeout: timeout - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_cmdq_detail_resp(void *hwdev, u8 mod, u8 cmd, struct sphw_cmd_buf *buf_in, - struct sphw_cmd_buf *buf_out, u64 *out_param, u32 timeout, u16 channel); - -/** - * @brief sphw_cos_id_detail_resp - cmdq detail message response - * @param hwdev: device pointer to hwdev - * @param mod: mod type - * @param cmd: cmd - * @param cos_id: cos id - * @param buf_in: message buffer in - * @param buf_out: message buffer out - * @param out_param: inline output data - * @param timeout: timeout - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_cos_id_detail_resp(void *hwdev, u8 mod, u8 cmd, u8 cos_id, struct sphw_cmd_buf *buf_in, - struct sphw_cmd_buf *buf_out, u64 *out_param, u32 timeout, u16 channel); - -/** - * @brief sphw_ppf_tmr_start - start ppf timer - * @param hwdev: device pointer to hwdev - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_ppf_tmr_start(void *hwdev); - -/** - * @brief sphw_ppf_tmr_stop - stop ppf timer - * @param hwdev: device pointer to hwdev - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_ppf_tmr_stop(void *hwdev); - -/** - * @brief sphw_func_tmr_bitmap_set - set timer bitmap status - * @param hwdev: device pointer to hwdev - * @param enable: 0-disable, 1-enable - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_func_tmr_bitmap_set(void *hwdev, bool enable); - -/** - * @brief sphw_get_board_info - get board info - * @param hwdev: device pointer to hwdev - * @param info: board info - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_get_board_info(void *hwdev, struct sphw_board_info *info, u16 channel); - -/** - * @brief sphw_set_wq_page_size - set work queue page size - * @param hwdev: device pointer to hwdev - * @param func_idx: function id - * @param page_size: page size - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int sphw_set_wq_page_size(void *hwdev, u16 func_idx, u32 page_size, u16 channel); - -/** - * @brief sphw_event_callback - evnet callback to notify service driver - * @param hwdev: device pointer to hwdev - * @param event: event info to service driver - */ -void sphw_event_callback(void *hwdev, struct sphw_event_info *event); - -/** - * @brief sphw_link_event_stats - link event stats - * @param hwdev: device pointer to hwdev - * @param link: link status - */ -void sphw_link_event_stats(void *dev, u8 link); - -enum func_reset_flag { - RES_TYPE_FLUSH_BIT = 0, - RES_TYPE_MQM, - RES_TYPE_SMF, - - RES_TYPE_COMM = 10, - RES_TYPE_COMM_MGMT_CH, - RES_TYPE_COMM_CMD_CH, - RES_TYPE_NIC, - RES_TYPE_OVS, - RES_TYPE_VBS, - RES_TYPE_ROCE, - RES_TYPE_FC, - RES_TYPE_TOE, - RES_TYPE_IPSEC, -}; - -#define SPHW_COMM_RES (BIT(RES_TYPE_COMM) | BIT(RES_TYPE_FLUSH_BIT) | BIT(RES_TYPE_MQM) | \ - BIT(RES_TYPE_SMF) | BIT(RES_TYPE_COMM_CMD_CH)) - -#define SPHW_NIC_RES BIT(RES_TYPE_NIC) -#define SPHW_FC_RES BIT(RES_TYPE_FC) - -/** - * @brief sphw_func_reset - reset func - * @param hwdev: device pointer to hwdev - * @param func_id: global function index - * @param reset_flag: reset flag - * @param channel: channel id - */ -int sphw_func_reset(void *dev, u16 func_id, u64 reset_flag, u16 channel); - -int sphw_get_dev_cap(void *hwdev); - -int sphw_set_bdf_ctxt(void *hwdev, u8 bus, u8 device, u8 function); - -int sphw_init_func_mbox_msg_channel(void *hwdev, u16 num_func); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c deleted file mode 100644 index 4b2674ec66f0..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c +++ /dev/null @@ -1,1341 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/mutex.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/module.h> -#include <linux/semaphore.h> - -#include "sphw_common.h" -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_hwdev.h" -#include "sphw_hwif.h" -#include "sphw_cfg_cmd.h" -#include "sphw_hw_cfg.h" - -uint g_rdma_mtts_num; - -uint intr_mode; -uint timer_enable = 1; -uint bloomfilter_enable; -uint g_test_mode; -uint g_test_qpc_num; -uint g_test_qpc_resvd_num; -uint g_test_pagesize_reorder; -uint g_test_xid_alloc_mode = 1; -uint g_test_gpa_check_enable = 1; -uint g_test_qpc_alloc_mode = 2; -uint g_test_scqc_alloc_mode = 2; -uint g_test_max_conn; -uint g_test_max_cache_conn; -uint g_test_scqc_num; -uint g_test_mpt_num; -uint g_test_mpt_resvd; -uint g_test_scq_resvd; -uint g_test_hash_num; -uint g_test_reorder_num; - -static void set_cfg_test_param(struct cfg_mgmt_info *cfg_mgmt) -{ - cfg_mgmt->svc_cap.test_mode = g_test_mode; - if (cfg_mgmt->svc_cap.test_mode == 0) - return; - - cfg_mgmt->svc_cap.timer_en = (u8)timer_enable; - cfg_mgmt->svc_cap.bloomfilter_en = (u8)bloomfilter_enable; - cfg_mgmt->svc_cap.test_qpc_num = g_test_qpc_num; - cfg_mgmt->svc_cap.test_qpc_resvd_num = g_test_qpc_resvd_num; - cfg_mgmt->svc_cap.test_page_size_reorder = g_test_pagesize_reorder; - cfg_mgmt->svc_cap.test_xid_alloc_mode = (bool)g_test_xid_alloc_mode; - cfg_mgmt->svc_cap.test_gpa_check_enable = (bool)g_test_gpa_check_enable; - cfg_mgmt->svc_cap.test_qpc_alloc_mode = (u8)g_test_qpc_alloc_mode; - cfg_mgmt->svc_cap.test_scqc_alloc_mode = (u8)g_test_scqc_alloc_mode; - cfg_mgmt->svc_cap.test_max_conn_num = g_test_max_conn; - cfg_mgmt->svc_cap.test_max_cache_conn_num = g_test_max_cache_conn; - cfg_mgmt->svc_cap.test_scqc_num = g_test_scqc_num; - cfg_mgmt->svc_cap.test_mpt_num = g_test_mpt_num; - cfg_mgmt->svc_cap.test_scq_resvd_num = g_test_scq_resvd; - cfg_mgmt->svc_cap.test_mpt_recvd_num = g_test_mpt_resvd; - cfg_mgmt->svc_cap.test_hash_num = g_test_hash_num; - cfg_mgmt->svc_cap.test_reorder_num = g_test_reorder_num; -} - -static void parse_pub_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct dev_sf_svc_attr *attr = &cap->sf_svc_attr; - - cap->host_id = dev_cap->host_id; - cap->ep_id = dev_cap->ep_id; - cap->er_id = dev_cap->er_id; - cap->port_id = dev_cap->port_id; - - cap->svc_type = dev_cap->svc_cap_en; - cap->chip_svc_type = cap->svc_type; - - cap->cos_valid_bitmap = dev_cap->valid_cos_bitmap; - cap->flexq_en = dev_cap->flexq_en; - - cap->host_total_function = dev_cap->host_total_func; - - if (type != TYPE_VF) { - cap->max_vf = dev_cap->max_vf; - cap->pf_num = dev_cap->host_pf_num; - cap->pf_id_start = dev_cap->pf_id_start; - cap->vf_num = dev_cap->host_vf_num; - cap->vf_id_start = dev_cap->vf_id_start; - } else { - cap->max_vf = 0; - } - - if (dev_cap->sf_svc_attr & SF_SVC_FT_BIT) - attr->ft_en = true; - else - attr->ft_en = false; - - if (dev_cap->sf_svc_attr & SF_SVC_RDMA_BIT) - attr->rdma_en = true; - else - attr->rdma_en = false; - - /* PPF will overwrite it when parse dynamic resource */ - if (dev_cap->func_sf_en) - cap->sf_en = true; - else - cap->sf_en = false; - - cap->lb_mode = dev_cap->lb_mode; - cap->smf_pg = dev_cap->smf_pg; - - cap->timer_en = (u8)timer_enable; /* timer enable */ - cap->host_oq_id_mask_val = dev_cap->host_oq_id_mask_val; - cap->max_connect_num = dev_cap->max_conn_num; - cap->max_stick2cache_num = dev_cap->max_stick2cache_num; - cap->bfilter_start_addr = dev_cap->max_bfilter_start_addr; - cap->bfilter_len = dev_cap->bfilter_len; - cap->hash_bucket_num = dev_cap->hash_bucket_num; - - sdk_info(hwdev->dev_hdl, "Get public resource capbility: svc_cap_en: 0x%x\n", - cap->svc_type); - sdk_info(hwdev->dev_hdl, "Host_id: 0x%x, ep_id: 0x%x, er_id: 0x%x, port_id: 0x%x, cos_bitmap: 0x%x, flexq: 0x%x\n", - cap->host_id, cap->ep_id, cap->er_id, cap->port_id, - cap->cos_valid_bitmap, cap->flexq_en); - sdk_info(hwdev->dev_hdl, "Host_total_function: 0x%x, host_oq_id_mask_val: 0x%x, max_vf: 0x%x\n", - cap->host_total_function, cap->host_oq_id_mask_val, - cap->max_vf); - sdk_info(hwdev->dev_hdl, "Host_pf_num: 0x%x, pf_id_start: 0x%x, host_vf_num: 0x%x, vf_id_start: 0x%x\n", - cap->pf_num, cap->pf_id_start, cap->vf_num, cap->vf_id_start); -} - -static void parse_dynamic_share_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct host_shared_resource_cap *shared_cap = &cap->shared_res_cap; - - if (dev_cap->host_sf_en) - cap->sf_en = true; - else - cap->sf_en = false; - - shared_cap->host_pctxs = dev_cap->host_pctx_num; - shared_cap->host_cctxs = dev_cap->host_ccxt_num; - shared_cap->host_scqs = dev_cap->host_scq_num; - shared_cap->host_srqs = dev_cap->host_srq_num; - shared_cap->host_mpts = dev_cap->host_mpt_num; - - sdk_info(hwdev->dev_hdl, "Dynamic share resource capbility:\n"); - sdk_info(hwdev->dev_hdl, "host_pctxs: 0x%x, host_cctxs: 0x%x, host_scqs: 0x%x, host_srqs: 0x%x, host_mpts: 0x%x\n", - shared_cap->host_pctxs, shared_cap->host_cctxs, - shared_cap->host_scqs, shared_cap->host_srqs, - shared_cap->host_mpts); -} - -static void parse_l2nic_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct nic_service_cap *nic_cap = &cap->nic_cap; - - nic_cap->max_sqs = dev_cap->nic_max_sq_id + 1; - nic_cap->max_rqs = dev_cap->nic_max_rq_id + 1; - - sdk_info(hwdev->dev_hdl, "L2nic resource capbility, max_sqs: 0x%x, max_rqs: 0x%x\n", - nic_cap->max_sqs, nic_cap->max_rqs); - - /* Check parameters from firmware */ - if (nic_cap->max_sqs > SPHW_CFG_MAX_QP || - nic_cap->max_rqs > SPHW_CFG_MAX_QP) { - sdk_info(hwdev->dev_hdl, "Number of qp exceed limit[1-%d]: sq: %u, rq: %u\n", - SPHW_CFG_MAX_QP, nic_cap->max_sqs, nic_cap->max_rqs); - nic_cap->max_sqs = SPHW_CFG_MAX_QP; - nic_cap->max_rqs = SPHW_CFG_MAX_QP; - } -} - -static void parse_fc_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct dev_fc_svc_cap *fc_cap = &cap->fc_cap.dev_fc_cap; - - fc_cap->max_parent_qpc_num = dev_cap->fc_max_pctx; - fc_cap->scq_num = dev_cap->fc_max_scq; - fc_cap->srq_num = dev_cap->fc_max_srq; - fc_cap->max_child_qpc_num = dev_cap->fc_max_cctx; - fc_cap->child_qpc_id_start = dev_cap->fc_cctx_id_start; - fc_cap->vp_id_start = dev_cap->fc_vp_id_start; - fc_cap->vp_id_end = dev_cap->fc_vp_id_end; - - sdk_info(hwdev->dev_hdl, "Get fc resource capbility\n"); - sdk_info(hwdev->dev_hdl, "Max_parent_qpc_num: 0x%x, scq_num: 0x%x, srq_num: 0x%x, max_child_qpc_num: 0x%x, child_qpc_id_start: 0x%x\n", - fc_cap->max_parent_qpc_num, fc_cap->scq_num, fc_cap->srq_num, - fc_cap->max_child_qpc_num, fc_cap->child_qpc_id_start); - sdk_info(hwdev->dev_hdl, "Vp_id_start: 0x%x, vp_id_end: 0x%x\n", - fc_cap->vp_id_start, fc_cap->vp_id_end); -} - -static void parse_roce_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct dev_roce_svc_own_cap *roce_cap = - &cap->rdma_cap.dev_rdma_cap.roce_own_cap; - - roce_cap->max_qps = dev_cap->roce_max_qp; - roce_cap->max_cqs = dev_cap->roce_max_cq; - roce_cap->max_srqs = dev_cap->roce_max_srq; - roce_cap->max_mpts = dev_cap->roce_max_mpt; - roce_cap->max_drc_qps = dev_cap->roce_max_drc_qp; - - roce_cap->wqe_cl_start = dev_cap->roce_wqe_cl_start; - roce_cap->wqe_cl_end = dev_cap->roce_wqe_cl_end; - roce_cap->wqe_cl_sz = dev_cap->roce_wqe_cl_size; - - sdk_info(hwdev->dev_hdl, "Get roce resource capbility, type: 0x%x\n", - type); - sdk_info(hwdev->dev_hdl, "Max_qps: 0x%x, max_cqs: 0x%x, max_srqs: 0x%x, max_mpts: 0x%x, max_drcts: 0x%x\n", - roce_cap->max_qps, roce_cap->max_cqs, roce_cap->max_srqs, - roce_cap->max_mpts, roce_cap->max_drc_qps); - - sdk_info(hwdev->dev_hdl, "Wqe_start: 0x%x, wqe_end: 0x%x, wqe_sz: 0x%x\n", - roce_cap->wqe_cl_start, roce_cap->wqe_cl_end, - roce_cap->wqe_cl_sz); - - if (roce_cap->max_qps == 0) { - if (type == TYPE_PF || type == TYPE_PPF) { - roce_cap->max_qps = 1024; - roce_cap->max_cqs = 2048; - roce_cap->max_srqs = 1024; - roce_cap->max_mpts = 1024; - roce_cap->max_drc_qps = 64; - } else { - roce_cap->max_qps = 512; - roce_cap->max_cqs = 1024; - roce_cap->max_srqs = 512; - roce_cap->max_mpts = 512; - roce_cap->max_drc_qps = 64; - } - } -} - -static void parse_rdma_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct dev_roce_svc_own_cap *roce_cap = - &cap->rdma_cap.dev_rdma_cap.roce_own_cap; - - roce_cap->cmtt_cl_start = dev_cap->roce_cmtt_cl_start; - roce_cap->cmtt_cl_end = dev_cap->roce_cmtt_cl_end; - roce_cap->cmtt_cl_sz = dev_cap->roce_cmtt_cl_size; - - roce_cap->dmtt_cl_start = dev_cap->roce_dmtt_cl_start; - roce_cap->dmtt_cl_end = dev_cap->roce_dmtt_cl_end; - roce_cap->dmtt_cl_sz = dev_cap->roce_dmtt_cl_size; - - sdk_info(hwdev->dev_hdl, "Get rdma resource capbility, Cmtt_start: 0x%x, cmtt_end: 0x%x, cmtt_sz: 0x%x\n", - roce_cap->cmtt_cl_start, roce_cap->cmtt_cl_end, - roce_cap->cmtt_cl_sz); - - sdk_info(hwdev->dev_hdl, "Dmtt_start: 0x%x, dmtt_end: 0x%x, dmtt_sz: 0x%x\n", - roce_cap->dmtt_cl_start, roce_cap->dmtt_cl_end, - roce_cap->dmtt_cl_sz); -} - -static void parse_ovs_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct ovs_service_cap *ovs_cap = &cap->ovs_cap; - - ovs_cap->dev_ovs_cap.max_pctxs = dev_cap->ovs_max_qpc; - ovs_cap->dev_ovs_cap.fake_vf_start_id = dev_cap->fake_vf_start_id; - ovs_cap->dev_ovs_cap.fake_vf_num = dev_cap->fake_vf_num; - ovs_cap->dev_ovs_cap.dynamic_qp_en = dev_cap->flexq_en; - - sdk_info(hwdev->dev_hdl, "Get ovs resource capbility, max_qpc: 0x%x, fake_vf_start_id: 0x%x, fake_vf_num: 0x%x, dynamic_qp_en: 0x%x\n", - ovs_cap->dev_ovs_cap.max_pctxs, - ovs_cap->dev_ovs_cap.fake_vf_start_id, - ovs_cap->dev_ovs_cap.fake_vf_num, - ovs_cap->dev_ovs_cap.dynamic_qp_en); -} - -static void parse_toe_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct dev_toe_svc_cap *toe_cap = &cap->toe_cap.dev_toe_cap; - - toe_cap->max_pctxs = dev_cap->toe_max_pctx; - toe_cap->max_cqs = dev_cap->toe_max_cq; - toe_cap->max_srqs = dev_cap->toe_max_srq; - toe_cap->srq_id_start = dev_cap->toe_srq_id_start; - toe_cap->max_mpts = dev_cap->toe_max_mpt; - - sdk_info(hwdev->dev_hdl, "Get toe resource capbility, max_pctxs: 0x%x, max_cqs: 0x%x, max_srqs: 0x%x, srq_id_start: 0x%x, max_mpts: 0x%x\n", - toe_cap->max_pctxs, toe_cap->max_cqs, toe_cap->max_srqs, - toe_cap->srq_id_start, toe_cap->max_mpts); -} - -static void parse_ipsec_res_cap(struct sphw_hwdev *hwdev, - struct service_cap *cap, - struct cfg_cmd_dev_cap *dev_cap, - enum func_type type) -{ - struct ipsec_service_cap *ipsec_cap = &cap->ipsec_cap; - - ipsec_cap->dev_ipsec_cap.max_sa_ctxs = dev_cap->ipsec_max_sactx; - - sdk_info(hwdev->dev_hdl, "Get IPsec resource capbility, max_sa_ctxs: 0x%x\n", - ipsec_cap->dev_ipsec_cap.max_sa_ctxs); -} - -static void parse_dev_cap(struct sphw_hwdev *dev, - struct cfg_cmd_dev_cap *dev_cap, enum func_type type) -{ - struct service_cap *cap = &dev->cfg_mgmt->svc_cap; - - /* Public resource */ - parse_pub_res_cap(dev, cap, dev_cap, type); - - /* PPF managed dynamic resource */ - if (type == TYPE_PPF) - parse_dynamic_share_res_cap(dev, cap, dev_cap, type); - - /* L2 NIC resource */ - if (IS_NIC_TYPE(dev)) - parse_l2nic_res_cap(dev, cap, dev_cap, type); - - /* FC without virtulization */ - if (type == TYPE_PF || type == TYPE_PPF) { - if (IS_FC_TYPE(dev)) - parse_fc_res_cap(dev, cap, dev_cap, type); - } - - /* toe resource */ - if (IS_TOE_TYPE(dev)) - parse_toe_res_cap(dev, cap, dev_cap, type); - - /* mtt cache line */ - if (IS_RDMA_ENABLE(dev)) - parse_rdma_res_cap(dev, cap, dev_cap, type); - - /* RoCE resource */ - if (IS_ROCE_TYPE(dev)) - parse_roce_res_cap(dev, cap, dev_cap, type); - - if (IS_OVS_TYPE(dev)) - parse_ovs_res_cap(dev, cap, dev_cap, type); - - if (IS_IPSEC_TYPE(dev)) - parse_ipsec_res_cap(dev, cap, dev_cap, type); -} - -static int get_cap_from_fw(struct sphw_hwdev *dev, enum func_type type) -{ - struct cfg_cmd_dev_cap dev_cap; - u16 out_len = sizeof(dev_cap); - int err; - - memset(&dev_cap, 0, sizeof(dev_cap)); - dev_cap.func_id = sphw_global_func_id(dev); - sdk_info(dev->dev_hdl, "Get cap from fw, func_idx: %u\n", - dev_cap.func_id); - - err = sphw_msg_to_mgmt_sync(dev, SPHW_MOD_CFGM, CFG_CMD_GET_DEV_CAP, - &dev_cap, sizeof(dev_cap), &dev_cap, &out_len, 0, - SPHW_CHANNEL_COMM); - if (err || dev_cap.head.status || !out_len) { - sdk_err(dev->dev_hdl, - "Failed to get capability from FW, err: %d, status: 0x%x, out size: 0x%x\n", - err, dev_cap.head.status, out_len); - return -EIO; - } - - parse_dev_cap(dev, &dev_cap, type); - - return 0; -} - -int sphw_get_dev_cap(void *dev) -{ - struct sphw_hwdev *hwdev = dev; - enum func_type type = SPHW_FUNC_TYPE(hwdev); - int err; - - switch (type) { - case TYPE_PF: - case TYPE_PPF: - case TYPE_VF: - err = get_cap_from_fw(hwdev, type); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to get PF/PPF capability\n"); - return err; - } - break; - default: - sdk_err(hwdev->dev_hdl, "Unsupported PCI Function type: %d\n", - type); - return -EINVAL; - } - - return 0; -} - -static void nic_param_fix(struct sphw_hwdev *dev) -{ -} - -static void rdma_mtt_fix(struct sphw_hwdev *dev) -{ - struct service_cap *cap = &dev->cfg_mgmt->svc_cap; - struct rdma_service_cap *rdma_cap = &cap->rdma_cap; - - rdma_cap->log_mtt = LOG_MTT_SEG; - rdma_cap->log_mtt_seg = LOG_MTT_SEG; - rdma_cap->mtt_entry_sz = MTT_ENTRY_SZ; - rdma_cap->mpt_entry_sz = RDMA_MPT_ENTRY_SZ; - rdma_cap->num_mtts = (g_rdma_mtts_num > 0 ? - g_rdma_mtts_num : RDMA_NUM_MTTS); -} - -static void rdma_param_fix(struct sphw_hwdev *dev) -{ - struct service_cap *cap = &dev->cfg_mgmt->svc_cap; - struct rdma_service_cap *rdma_cap = &cap->rdma_cap; - struct dev_roce_svc_own_cap *roce_cap = - &rdma_cap->dev_rdma_cap.roce_own_cap; - - rdma_cap->log_mtt = LOG_MTT_SEG; - rdma_cap->log_rdmarc = LOG_RDMARC_SEG; - rdma_cap->reserved_qps = RDMA_RSVD_QPS; - rdma_cap->max_sq_sg = RDMA_MAX_SQ_SGE; - - /* RoCE */ - if (IS_ROCE_TYPE(dev)) { - roce_cap->qpc_entry_sz = ROCE_QPC_ENTRY_SZ; - roce_cap->max_wqes = ROCE_MAX_WQES; - roce_cap->max_rq_sg = ROCE_MAX_RQ_SGE; - roce_cap->max_sq_inline_data_sz = ROCE_MAX_SQ_INLINE_DATA_SZ; - roce_cap->max_rq_desc_sz = ROCE_MAX_RQ_DESC_SZ; - roce_cap->rdmarc_entry_sz = ROCE_RDMARC_ENTRY_SZ; - roce_cap->max_qp_init_rdma = ROCE_MAX_QP_INIT_RDMA; - roce_cap->max_qp_dest_rdma = ROCE_MAX_QP_DEST_RDMA; - roce_cap->max_srq_wqes = ROCE_MAX_SRQ_WQES; - roce_cap->reserved_srqs = ROCE_RSVD_SRQS; - roce_cap->max_srq_sge = ROCE_MAX_SRQ_SGE; - roce_cap->srqc_entry_sz = ROCE_SRQC_ENTERY_SZ; - roce_cap->max_msg_sz = ROCE_MAX_MSG_SZ; - } - - rdma_cap->max_sq_desc_sz = RDMA_MAX_SQ_DESC_SZ; - rdma_cap->wqebb_size = WQEBB_SZ; - rdma_cap->max_cqes = RDMA_MAX_CQES; - rdma_cap->reserved_cqs = RDMA_RSVD_CQS; - rdma_cap->cqc_entry_sz = RDMA_CQC_ENTRY_SZ; - rdma_cap->cqe_size = RDMA_CQE_SZ; - rdma_cap->reserved_mrws = RDMA_RSVD_MRWS; - rdma_cap->mpt_entry_sz = RDMA_MPT_ENTRY_SZ; - - /* 2^8 - 1 - * +------------------------+-----------+ - * | 4B | 1M(20b) | Key(8b) | - * +------------------------+-----------+ - * key = 8bit key + 24bit index, - * now Lkey of SGE uses 2bit(bit31 and bit30), so key only have 10bit, - * we use original 8bits directly for simpilification - */ - rdma_cap->max_fmr_maps = 255; - rdma_cap->num_mtts = (g_rdma_mtts_num > 0 ? - g_rdma_mtts_num : RDMA_NUM_MTTS); - rdma_cap->log_mtt_seg = LOG_MTT_SEG; - rdma_cap->mtt_entry_sz = MTT_ENTRY_SZ; - rdma_cap->log_rdmarc_seg = LOG_RDMARC_SEG; - rdma_cap->local_ca_ack_delay = LOCAL_ACK_DELAY; - rdma_cap->num_ports = RDMA_NUM_PORTS; - rdma_cap->db_page_size = DB_PAGE_SZ; - rdma_cap->direct_wqe_size = DWQE_SZ; - rdma_cap->num_pds = NUM_PD; - rdma_cap->reserved_pds = RSVD_PD; - rdma_cap->max_xrcds = MAX_XRCDS; - rdma_cap->reserved_xrcds = RSVD_XRCDS; - rdma_cap->max_gid_per_port = MAX_GID_PER_PORT; - rdma_cap->gid_entry_sz = GID_ENTRY_SZ; - rdma_cap->reserved_lkey = RSVD_LKEY; - rdma_cap->num_comp_vectors = (u32)dev->cfg_mgmt->eq_info.num_ceq; - rdma_cap->page_size_cap = PAGE_SZ_CAP; - rdma_cap->flags = (RDMA_BMME_FLAG_LOCAL_INV | - RDMA_BMME_FLAG_REMOTE_INV | - RDMA_BMME_FLAG_FAST_REG_WR | - RDMA_DEV_CAP_FLAG_XRC | - RDMA_DEV_CAP_FLAG_MEM_WINDOW | - RDMA_BMME_FLAG_TYPE_2_WIN | - RDMA_BMME_FLAG_WIN_TYPE_2B | - RDMA_DEV_CAP_FLAG_ATOMIC); - rdma_cap->max_frpl_len = MAX_FRPL_LEN; - rdma_cap->max_pkeys = MAX_PKEYS; -} - -static void toe_param_fix(struct sphw_hwdev *dev) -{ - struct service_cap *cap = &dev->cfg_mgmt->svc_cap; - struct toe_service_cap *toe_cap = &cap->toe_cap; - - toe_cap->pctx_sz = TOE_PCTX_SZ; - toe_cap->scqc_sz = TOE_CQC_SZ; -} - -static void ovs_param_fix(struct sphw_hwdev *dev) -{ - struct service_cap *cap = &dev->cfg_mgmt->svc_cap; - struct ovs_service_cap *ovs_cap = &cap->ovs_cap; - - ovs_cap->pctx_sz = OVS_PCTX_SZ; -} - -static void fc_param_fix(struct sphw_hwdev *dev) -{ - struct service_cap *cap = &dev->cfg_mgmt->svc_cap; - struct fc_service_cap *fc_cap = &cap->fc_cap; - - fc_cap->parent_qpc_size = FC_PCTX_SZ; - fc_cap->child_qpc_size = FC_CCTX_SZ; - fc_cap->sqe_size = FC_SQE_SZ; - - fc_cap->scqc_size = FC_SCQC_SZ; - fc_cap->scqe_size = FC_SCQE_SZ; - - fc_cap->srqc_size = FC_SRQC_SZ; - fc_cap->srqe_size = FC_SRQE_SZ; -} - -static void ipsec_param_fix(struct sphw_hwdev *dev) -{ - struct service_cap *cap = &dev->cfg_mgmt->svc_cap; - struct ipsec_service_cap *ipsec_cap = &cap->ipsec_cap; - - ipsec_cap->sactx_sz = IPSEC_SACTX_SZ; -} - -static void init_service_param(struct sphw_hwdev *dev) -{ - if (IS_NIC_TYPE(dev)) - nic_param_fix(dev); - if (IS_RDMA_ENABLE(dev)) - rdma_mtt_fix(dev); - if (IS_ROCE_TYPE(dev)) - rdma_param_fix(dev); - if (IS_FC_TYPE(dev)) - fc_param_fix(dev); - if (IS_TOE_TYPE(dev)) - toe_param_fix(dev); - if (IS_OVS_TYPE(dev)) - ovs_param_fix(dev); - if (IS_IPSEC_TYPE(dev)) - ipsec_param_fix(dev); -} - -static void cfg_get_eq_num(struct sphw_hwdev *dev) -{ - struct cfg_eq_info *eq_info = &dev->cfg_mgmt->eq_info; - - eq_info->num_ceq = dev->hwif->attr.num_ceqs; - eq_info->num_ceq_remain = eq_info->num_ceq; -} - -static int cfg_init_eq(struct sphw_hwdev *dev) -{ - struct cfg_mgmt_info *cfg_mgmt = dev->cfg_mgmt; - struct cfg_eq *eq = NULL; - u8 num_ceq, i = 0; - - cfg_get_eq_num(dev); - num_ceq = cfg_mgmt->eq_info.num_ceq; - - sdk_info(dev->dev_hdl, "Cfg mgmt: ceqs=0x%x, remain=0x%x\n", - cfg_mgmt->eq_info.num_ceq, cfg_mgmt->eq_info.num_ceq_remain); - - if (!num_ceq) { - sdk_err(dev->dev_hdl, "Ceq num cfg in fw is zero\n"); - return -EFAULT; - } - - eq = kcalloc(num_ceq, sizeof(*eq), GFP_KERNEL); - if (!eq) - return -ENOMEM; - - for (i = 0; i < num_ceq; ++i) { - eq[i].eqn = i; - eq[i].free = CFG_FREE; - eq[i].type = SERVICE_T_MAX; - } - - cfg_mgmt->eq_info.eq = eq; - - mutex_init(&cfg_mgmt->eq_info.eq_mutex); - - return 0; -} - -int sphw_vector_to_eqn(void *hwdev, enum sphw_service_type type, int vector) -{ - struct sphw_hwdev *dev = hwdev; - struct cfg_mgmt_info *cfg_mgmt = NULL; - struct cfg_eq *eq = NULL; - int eqn = -EINVAL; - - if (!hwdev || vector < 0) - return -EINVAL; - - if (type != SERVICE_T_ROCE) { - sdk_err(dev->dev_hdl, - "Service type :%d, only RDMA service could get eqn by vector.\n", - type); - return -EINVAL; - } - - cfg_mgmt = dev->cfg_mgmt; - vector = (vector % cfg_mgmt->eq_info.num_ceq) + CFG_RDMA_CEQ_BASE; - - eq = cfg_mgmt->eq_info.eq; - if (eq[vector].type == SERVICE_T_ROCE && eq[vector].free == CFG_BUSY) - eqn = eq[vector].eqn; - - return eqn; -} - -static int cfg_init_interrupt(struct sphw_hwdev *dev) -{ - struct cfg_mgmt_info *cfg_mgmt = dev->cfg_mgmt; - struct cfg_irq_info *irq_info = &cfg_mgmt->irq_param_info; - u16 intr_num = dev->hwif->attr.num_irqs; - - if (!intr_num) { - sdk_err(dev->dev_hdl, "Irq num cfg in fw is zero\n"); - return -EFAULT; - } - irq_info->alloc_info = kcalloc(intr_num, sizeof(*irq_info->alloc_info), - GFP_KERNEL); - if (!irq_info->alloc_info) - return -ENOMEM; - - irq_info->num_irq_hw = intr_num; - - /* Production requires VF only surppots MSI-X */ - if (SPHW_FUNC_TYPE(dev) == TYPE_VF) - cfg_mgmt->svc_cap.interrupt_type = INTR_TYPE_MSIX; - else - cfg_mgmt->svc_cap.interrupt_type = intr_mode; - - mutex_init(&irq_info->irq_mutex); - return 0; -} - -static int cfg_enable_interrupt(struct sphw_hwdev *dev) -{ - struct cfg_mgmt_info *cfg_mgmt = dev->cfg_mgmt; - u16 nreq = cfg_mgmt->irq_param_info.num_irq_hw; - - void *pcidev = dev->pcidev_hdl; - struct irq_alloc_info_st *irq_info = NULL; - struct msix_entry *entry = NULL; - u16 i = 0; - int actual_irq; - - irq_info = cfg_mgmt->irq_param_info.alloc_info; - - sdk_info(dev->dev_hdl, "Interrupt type: %u, irq num: %u.\n", - cfg_mgmt->svc_cap.interrupt_type, nreq); - - switch (cfg_mgmt->svc_cap.interrupt_type) { - case INTR_TYPE_MSIX: - if (!nreq) { - sdk_err(dev->dev_hdl, "Interrupt number cannot be zero\n"); - return -EINVAL; - } - entry = kcalloc(nreq, sizeof(*entry), GFP_KERNEL); - if (!entry) - return -ENOMEM; - - for (i = 0; i < nreq; i++) - entry[i].entry = i; - - actual_irq = pci_enable_msix_range(pcidev, entry, - VECTOR_THRESHOLD, nreq); - if (actual_irq < 0) { - sdk_err(dev->dev_hdl, "Alloc msix entries with threshold 2 failed. actual_irq: %d\n", - actual_irq); - kfree(entry); - return -ENOMEM; - } - - nreq = (u16)actual_irq; - cfg_mgmt->irq_param_info.num_total = nreq; - cfg_mgmt->irq_param_info.num_irq_remain = nreq; - sdk_info(dev->dev_hdl, "Request %u msix vector success.\n", - nreq); - - for (i = 0; i < nreq; ++i) { - /* u16 driver uses to specify entry, OS writes */ - irq_info[i].info.msix_entry_idx = entry[i].entry; - /* u32 kernel uses to write allocated vector */ - irq_info[i].info.irq_id = entry[i].vector; - irq_info[i].type = SERVICE_T_MAX; - irq_info[i].free = CFG_FREE; - } - - kfree(entry); - - break; - - default: - sdk_err(dev->dev_hdl, "Unsupport interrupt type %d\n", - cfg_mgmt->svc_cap.interrupt_type); - break; - } - - return 0; -} - -int sphw_alloc_irqs(void *hwdev, enum sphw_service_type type, u16 num, - struct irq_info *irq_info_array, u16 *act_num) -{ - struct sphw_hwdev *dev = hwdev; - struct cfg_mgmt_info *cfg_mgmt = NULL; - struct cfg_irq_info *irq_info = NULL; - struct irq_alloc_info_st *alloc_info = NULL; - int max_num_irq; - u16 free_num_irq; - int i, j; - - if (!hwdev || !irq_info_array || !act_num) - return -EINVAL; - - cfg_mgmt = dev->cfg_mgmt; - irq_info = &cfg_mgmt->irq_param_info; - alloc_info = irq_info->alloc_info; - max_num_irq = irq_info->num_total; - free_num_irq = irq_info->num_irq_remain; - - mutex_lock(&irq_info->irq_mutex); - - if (num > free_num_irq) { - if (free_num_irq == 0) { - sdk_err(dev->dev_hdl, - "no free irq resource in cfg mgmt.\n"); - mutex_unlock(&irq_info->irq_mutex); - return -ENOMEM; - } - - sdk_warn(dev->dev_hdl, "only %u irq resource in cfg mgmt.\n", - free_num_irq); - num = free_num_irq; - } - - *act_num = 0; - - for (i = 0; i < num; i++) { - for (j = 0; j < max_num_irq; j++) { - if (alloc_info[j].free == CFG_FREE) { - if (irq_info->num_irq_remain == 0) { - sdk_err(dev->dev_hdl, "No free irq resource in cfg mgmt\n"); - mutex_unlock(&irq_info->irq_mutex); - return -EINVAL; - } - alloc_info[j].type = type; - alloc_info[j].free = CFG_BUSY; - - irq_info_array[i].msix_entry_idx = - alloc_info[j].info.msix_entry_idx; - irq_info_array[i].irq_id = - alloc_info[j].info.irq_id; - (*act_num)++; - irq_info->num_irq_remain--; - - break; - } - } - } - - mutex_unlock(&irq_info->irq_mutex); - return 0; -} - -void sphw_free_irq(void *hwdev, enum sphw_service_type type, u32 irq_id) -{ - struct sphw_hwdev *dev = hwdev; - struct cfg_mgmt_info *cfg_mgmt = NULL; - struct cfg_irq_info *irq_info = NULL; - struct irq_alloc_info_st *alloc_info = NULL; - int max_num_irq; - int i; - - if (!hwdev) - return; - - cfg_mgmt = dev->cfg_mgmt; - irq_info = &cfg_mgmt->irq_param_info; - alloc_info = irq_info->alloc_info; - max_num_irq = irq_info->num_total; - - mutex_lock(&irq_info->irq_mutex); - - for (i = 0; i < max_num_irq; i++) { - if (irq_id == alloc_info[i].info.irq_id && - type == alloc_info[i].type) { - if (alloc_info[i].free == CFG_BUSY) { - alloc_info[i].free = CFG_FREE; - irq_info->num_irq_remain++; - if (irq_info->num_irq_remain > max_num_irq) { - sdk_err(dev->dev_hdl, "Find target,but over range\n"); - mutex_unlock(&irq_info->irq_mutex); - return; - } - break; - } - } - } - - if (i >= max_num_irq) - sdk_warn(dev->dev_hdl, "Irq %u don`t need to free\n", irq_id); - - mutex_unlock(&irq_info->irq_mutex); -} - -int sphw_vector_to_irq(void *hwdev, enum sphw_service_type type, int vector) -{ - struct sphw_hwdev *dev = hwdev; - struct cfg_mgmt_info *cfg_mgmt = NULL; - struct irq_alloc_info_st *irq_info = NULL; - int irq = -EINVAL; - - if (!hwdev) - return -EINVAL; - - cfg_mgmt = dev->cfg_mgmt; - if (type != SERVICE_T_ROCE) { - sdk_err(dev->dev_hdl, - "Service type: %u, only RDMA service could get eqn by vector\n", - type); - return -EINVAL; - } - - /* Current RDMA CEQ are 2 - 31, will change in the future */ - vector = ((vector % cfg_mgmt->eq_info.num_ceq) + CFG_RDMA_CEQ_BASE); - - irq_info = cfg_mgmt->irq_param_info.alloc_info; - if (irq_info[vector].type == SERVICE_T_ROCE) - if (irq_info[vector].free == CFG_BUSY) - irq = (int)irq_info[vector].info.irq_id; - - return irq; -} - -int sphw_alloc_ceqs(void *hwdev, enum sphw_service_type type, int num, int *ceq_id_array, - int *act_num) -{ - struct sphw_hwdev *dev = hwdev; - struct cfg_mgmt_info *cfg_mgmt = NULL; - struct cfg_eq_info *eq = NULL; - int free_ceq; - int i, j; - - if (!hwdev || !ceq_id_array || !act_num) - return -EINVAL; - - cfg_mgmt = dev->cfg_mgmt; - eq = &cfg_mgmt->eq_info; - free_ceq = eq->num_ceq_remain; - - mutex_lock(&eq->eq_mutex); - - if (num > free_ceq) { - if (free_ceq <= 0) { - sdk_err(dev->dev_hdl, "No free ceq resource in cfg mgmt\n"); - mutex_unlock(&eq->eq_mutex); - return -ENOMEM; - } - - sdk_warn(dev->dev_hdl, "Only %d ceq resource in cfg mgmt\n", - free_ceq); - } - - *act_num = 0; - - num = min(num, eq->num_ceq - CFG_RDMA_CEQ_BASE); - for (i = 0; i < num; i++) { - if (eq->num_ceq_remain == 0) { - sdk_warn(dev->dev_hdl, "Alloc %d ceqs, less than required %d ceqs\n", - *act_num, num); - mutex_unlock(&eq->eq_mutex); - return 0; - } - - for (j = CFG_RDMA_CEQ_BASE; j < eq->num_ceq; j++) { - if (eq->eq[j].free == CFG_FREE) { - eq->eq[j].type = type; - eq->eq[j].free = CFG_BUSY; - eq->num_ceq_remain--; - ceq_id_array[i] = eq->eq[j].eqn; - (*act_num)++; - break; - } - } - } - - mutex_unlock(&eq->eq_mutex); - return 0; -} - -void sphw_free_ceq(void *hwdev, enum sphw_service_type type, int ceq_id) -{ - struct sphw_hwdev *dev = hwdev; - struct cfg_mgmt_info *cfg_mgmt = NULL; - struct cfg_eq_info *eq = NULL; - u8 num_ceq; - u8 i = 0; - - if (!hwdev) - return; - - cfg_mgmt = dev->cfg_mgmt; - eq = &cfg_mgmt->eq_info; - num_ceq = eq->num_ceq; - - mutex_lock(&eq->eq_mutex); - - for (i = 0; i < num_ceq; i++) { - if (ceq_id == eq->eq[i].eqn && - type == cfg_mgmt->eq_info.eq[i].type) { - if (eq->eq[i].free == CFG_BUSY) { - eq->eq[i].free = CFG_FREE; - eq->num_ceq_remain++; - if (eq->num_ceq_remain > num_ceq) - eq->num_ceq_remain %= num_ceq; - - mutex_unlock(&eq->eq_mutex); - return; - } - } - } - - if (i >= num_ceq) - sdk_warn(dev->dev_hdl, "ceq %d don`t need to free.\n", ceq_id); - - mutex_unlock(&eq->eq_mutex); -} - -int init_cfg_mgmt(struct sphw_hwdev *dev) -{ - int err; - struct cfg_mgmt_info *cfg_mgmt; - - cfg_mgmt = kzalloc(sizeof(*cfg_mgmt), GFP_KERNEL); - if (!cfg_mgmt) - return -ENOMEM; - - dev->cfg_mgmt = cfg_mgmt; - cfg_mgmt->hwdev = dev; - - err = cfg_init_eq(dev); - if (err) { - sdk_err(dev->dev_hdl, "Failed to init cfg event queue, err: %d\n", - err); - goto free_mgmt_mem; - } - - err = cfg_init_interrupt(dev); - if (err) { - sdk_err(dev->dev_hdl, "Failed to init cfg interrupt, err: %d\n", - err); - goto free_eq_mem; - } - - err = cfg_enable_interrupt(dev); - if (err) { - sdk_err(dev->dev_hdl, "Failed to enable cfg interrupt, err: %d\n", - err); - goto free_interrupt_mem; - } - - return 0; - -free_interrupt_mem: - kfree(cfg_mgmt->irq_param_info.alloc_info); - cfg_mgmt->irq_param_info.alloc_info = NULL; - -free_eq_mem: - kfree(cfg_mgmt->eq_info.eq); - cfg_mgmt->eq_info.eq = NULL; - -free_mgmt_mem: - kfree(cfg_mgmt); - return err; -} - -void free_cfg_mgmt(struct sphw_hwdev *dev) -{ - struct cfg_mgmt_info *cfg_mgmt = dev->cfg_mgmt; - - /* if the allocated resource were recycled */ - if (cfg_mgmt->irq_param_info.num_irq_remain != - cfg_mgmt->irq_param_info.num_total || - cfg_mgmt->eq_info.num_ceq_remain != cfg_mgmt->eq_info.num_ceq) - sdk_err(dev->dev_hdl, "Can't reclaim all irq and event queue, please check\n"); - - switch (cfg_mgmt->svc_cap.interrupt_type) { - case INTR_TYPE_MSIX: - pci_disable_msix(dev->pcidev_hdl); - break; - - case INTR_TYPE_MSI: - pci_disable_msi(dev->pcidev_hdl); - break; - - case INTR_TYPE_INT: - default: - break; - } - - kfree(cfg_mgmt->irq_param_info.alloc_info); - cfg_mgmt->irq_param_info.alloc_info = NULL; - - kfree(cfg_mgmt->eq_info.eq); - cfg_mgmt->eq_info.eq = NULL; - - kfree(cfg_mgmt); -} - -int init_capability(struct sphw_hwdev *dev) -{ - int err; - struct cfg_mgmt_info *cfg_mgmt = dev->cfg_mgmt; - - set_cfg_test_param(cfg_mgmt); - - cfg_mgmt->svc_cap.sf_svc_attr.ft_pf_en = false; - cfg_mgmt->svc_cap.sf_svc_attr.rdma_pf_en = false; - - err = sphw_get_dev_cap(dev); - if (err) - return err; - - init_service_param(dev); - - sdk_info(dev->dev_hdl, "Init capability success\n"); - return 0; -} - -void free_capability(struct sphw_hwdev *dev) -{ - sdk_info(dev->dev_hdl, "Free capability success"); -} - -bool sphw_support_nic(void *hwdev, struct nic_service_cap *cap) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - if (!IS_NIC_TYPE(dev)) - return false; - - if (cap) - memcpy(cap, &dev->cfg_mgmt->svc_cap.nic_cap, sizeof(*cap)); - - return true; -} - -bool sphw_support_ipsec(void *hwdev, struct ipsec_service_cap *cap) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - if (!IS_IPSEC_TYPE(dev)) - return false; - - if (cap) - memcpy(cap, &dev->cfg_mgmt->svc_cap.ipsec_cap, sizeof(*cap)); - - return true; -} - -bool sphw_support_roce(void *hwdev, struct rdma_service_cap *cap) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - if (!IS_ROCE_TYPE(dev)) - return false; - - if (cap) - memcpy(cap, &dev->cfg_mgmt->svc_cap.rdma_cap, sizeof(*cap)); - - return true; -} - -bool sphw_support_fc(void *hwdev, struct fc_service_cap *cap) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - if (!IS_FC_TYPE(dev)) - return false; - - if (cap) - memcpy(cap, &dev->cfg_mgmt->svc_cap.fc_cap, sizeof(*cap)); - - return true; -} - -bool sphw_support_rdma(void *hwdev, struct rdma_service_cap *cap) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - if (!IS_RDMA_TYPE(dev)) - return false; - - if (cap) - memcpy(cap, &dev->cfg_mgmt->svc_cap.rdma_cap, sizeof(*cap)); - - return true; -} - -bool sphw_support_ovs(void *hwdev, struct ovs_service_cap *cap) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - if (!IS_OVS_TYPE(dev)) - return false; - - if (cap) - memcpy(cap, &dev->cfg_mgmt->svc_cap.ovs_cap, sizeof(*cap)); - - return true; -} - -/* Only PPF support it, PF is not */ -bool sphw_support_toe(void *hwdev, struct toe_service_cap *cap) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - if (!IS_TOE_TYPE(dev)) - return false; - - if (cap) - memcpy(cap, &dev->cfg_mgmt->svc_cap.toe_cap, sizeof(*cap)); - - return true; -} - -bool sphw_func_for_mgmt(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - if (dev->cfg_mgmt->svc_cap.chip_svc_type >= CFG_SVC_NIC_BIT0) - return false; - else - return true; -} - -bool sphw_get_stateful_enable(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return false; - - return dev->cfg_mgmt->svc_cap.sf_en; -} - -u8 sphw_host_oq_id_mask(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting host oq id mask\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.host_oq_id_mask_val; -} - -u8 sphw_host_id(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting host id\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.host_id; -} - -u16 sphw_host_total_func(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting host total function number\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.host_total_function; -} - -u16 sphw_func_max_qnum(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting function max queue number\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.nic_cap.max_sqs; -} - -u16 sphw_func_max_nic_qnum(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting function max queue number\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.nic_cap.max_sqs; -} - -u8 sphw_ep_id(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting ep id\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.ep_id; -} - -u8 sphw_er_id(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting er id\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.er_id; -} - -u8 sphw_physical_port_id(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting physical port id\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.port_id; -} - -u16 sphw_func_max_vf(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting max vf number\n"); - return 0; - } - return dev->cfg_mgmt->svc_cap.max_vf; -} - -u8 sphw_cos_valid_bitmap(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting cos valid bitmap\n"); - return 0; - } - return (u8)(dev->cfg_mgmt->svc_cap.cos_valid_bitmap); -} - -void sphw_shutdown_hwdev(void *hwdev) -{ - /* to do : if IS_SLAVE_HOST*/ -} - -u32 sphw_host_pf_num(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for getting pf number capability\n"); - return 0; - } - - return dev->cfg_mgmt->svc_cap.pf_num; -} - -u8 sphw_flexq_en(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return 0; - - return dev->cfg_mgmt->svc_cap.flexq_en; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h deleted file mode 100644 index 1b48e0991563..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h +++ /dev/null @@ -1,329 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_HW_CFG_H -#define SPHW_HW_CFG_H - -#include <linux/types.h> - -#define CFG_MAX_CMD_TIMEOUT 30000 /* ms */ - -enum { - CFG_FREE = 0, - CFG_BUSY = 1 -}; - -/* start position for CEQs allocation, Max number of CEQs is 32 */ -enum { - CFG_RDMA_CEQ_BASE = 0 -}; - -enum { - SF_SVC_FT_BIT = (1 << 0), - SF_SVC_RDMA_BIT = (1 << 1), -}; - -/* RDMA resource */ -#define K_UNIT BIT(10) -#define M_UNIT BIT(20) -#define G_UNIT BIT(30) - -/* L2NIC */ -#define SPHW_CFG_MAX_QP 256 - -/* RDMA */ -#define RDMA_RSVD_QPS 2 -#define ROCE_MAX_WQES (32 * K_UNIT - 1) -#define IWARP_MAX_WQES (8 * K_UNIT) - -#define RDMA_MAX_SQ_SGE 32 - -#define ROCE_MAX_RQ_SGE 16 - -#define RDMA_MAX_SQ_DESC_SZ (1 * K_UNIT) - -/* (256B(cache_line_len) - 16B(ctrl_seg_len) - 64B(max_task_seg_len)) */ -#define ROCE_MAX_SQ_INLINE_DATA_SZ 912 - -#define ROCE_MAX_RQ_DESC_SZ 256 - -#define ROCE_QPC_ENTRY_SZ 512 - -#define WQEBB_SZ 64 - -#define ROCE_RDMARC_ENTRY_SZ 32 -#define ROCE_MAX_QP_INIT_RDMA 128 -#define ROCE_MAX_QP_DEST_RDMA 128 - -#define ROCE_MAX_SRQ_WQES (16 * K_UNIT - 1) -#define ROCE_RSVD_SRQS 0 -#define ROCE_MAX_SRQ_SGE 15 -#define ROCE_SRQC_ENTERY_SZ 64 - -#define RDMA_MAX_CQES (8 * M_UNIT - 1) -#define RDMA_RSVD_CQS 0 - -#define RDMA_CQC_ENTRY_SZ 128 - -#define RDMA_CQE_SZ 64 -#define RDMA_RSVD_MRWS 128 -#define RDMA_MPT_ENTRY_SZ 64 -#define RDMA_NUM_MTTS (1 * G_UNIT) -#define LOG_MTT_SEG 5 -#define MTT_ENTRY_SZ 8 -#define LOG_RDMARC_SEG 3 - -#define LOCAL_ACK_DELAY 15 -#define RDMA_NUM_PORTS 1 -#define ROCE_MAX_MSG_SZ (2 * G_UNIT) - -#define DB_PAGE_SZ (4 * K_UNIT) -#define DWQE_SZ 256 - -#define NUM_PD (128 * K_UNIT) -#define RSVD_PD 0 - -#define MAX_XRCDS (64 * K_UNIT) -#define RSVD_XRCDS 0 - -#define MAX_GID_PER_PORT 128 -#define GID_ENTRY_SZ 32 -#define RSVD_LKEY ((RDMA_RSVD_MRWS - 1) << 8) -#define NUM_COMP_VECTORS 32 -#define PAGE_SZ_CAP ((1UL << 12) | (1UL << 16) | (1UL << 21)) -#define ROCE_MODE 1 - -#define MAX_FRPL_LEN 511 -#define MAX_PKEYS 1 - -/* ToE */ -#define TOE_PCTX_SZ 1024 -#define TOE_CQC_SZ 64 - -/* IoE */ -#define IOE_PCTX_SZ 512 - -/* FC */ -#define FC_PCTX_SZ 256 -#define FC_CCTX_SZ 256 -#define FC_SQE_SZ 128 -#define FC_SCQC_SZ 64 -#define FC_SCQE_SZ 64 -#define FC_SRQC_SZ 64 -#define FC_SRQE_SZ 32 - -/* OVS */ -#define OVS_PCTX_SZ 512 - -/* IPsec */ -#define IPSEC_SACTX_SZ 512 - -struct dev_sf_svc_attr { - bool ft_en; /* business enable flag (not include RDMA) */ - bool ft_pf_en; /* In FPGA Test VF resource is in PF or not, - * 0 - VF, 1 - PF, VF doesn't need this bit. - */ - bool rdma_en; - bool rdma_pf_en;/* In FPGA Test VF RDMA resource is in PF or not, - * 0 - VF, 1 - PF, VF doesn't need this bit. - */ -}; - -struct host_shared_resource_cap { - u32 host_pctxs; /* Parent Context max 1M, IOE and FCoE max 8K flows */ - u32 host_cctxs; /* Child Context: max 8K */ - u32 host_scqs; /* shared CQ, chip interface module uses 1 SCQ - * TOE/IOE/FCoE each uses 1 SCQ - * RoCE/IWARP uses multiple SCQs - * So 6 SCQ least - */ - u32 host_srqs; /* SRQ number: 256K */ - u32 host_mpts; /* MR number:1M */ -}; - -enum intr_type { - INTR_TYPE_MSIX, - INTR_TYPE_MSI, - INTR_TYPE_INT, - INTR_TYPE_NONE, - /* PXE,OVS need single thread processing, - * synchronization messages must use poll wait mechanism interface - */ -}; - -/* service type relates define */ -enum cfg_svc_type_en { - CFG_SVC_NIC_BIT0 = (1 << 0), - CFG_SVC_ROCE_BIT1 = (1 << 1), - CFG_SVC_VBS_BIT2 = (1 << 2), - CFG_SVC_TOE_BIT3 = (1 << 3), - CFG_SVC_IPSEC_BIT4 = (1 << 4), - CFG_SVC_FC_BIT5 = (1 << 5), - CFG_SVC_VIRTIO_BIT6 = (1 << 6), - CFG_SVC_OVS_BIT7 = (1 << 7), - CFG_SVC_RSV2_BIT8 = (1 << 8), - CFG_SVC_IOE_BIT9 = (1 << 9), - - CFG_SVC_FT_EN = (CFG_SVC_VBS_BIT2 | CFG_SVC_TOE_BIT3 | - CFG_SVC_IPSEC_BIT4 | CFG_SVC_FC_BIT5 | - CFG_SVC_VIRTIO_BIT6 | CFG_SVC_OVS_BIT7 | - CFG_SVC_IOE_BIT9), - CFG_SVC_RDMA_EN = CFG_SVC_ROCE_BIT1 -}; - -/* device capability */ -struct service_cap { - struct dev_sf_svc_attr sf_svc_attr; - enum cfg_svc_type_en svc_type; /* user input service type */ - enum cfg_svc_type_en chip_svc_type; /* HW supported service type */ - - u8 host_id; - u8 ep_id; - u8 er_id; /* PF/VF's ER */ - u8 port_id; /* PF/VF's physical port */ - - /* Host global resources */ - u16 host_total_function; - u8 pf_num; - u8 pf_id_start; - u16 vf_num; /* max numbers of vf in current host */ - u16 vf_id_start; - u8 host_oq_id_mask_val; - - u8 flexq_en; - u8 cos_valid_bitmap; - u16 max_vf; /* max VF number that PF supported */ - - /* DO NOT get interrupt_type from firmware */ - enum intr_type interrupt_type; - - bool sf_en; /* stateful business status */ - u8 timer_en; /* 0:disable, 1:enable */ - u8 bloomfilter_en; /* 0:disable, 1:enable*/ - - u8 lb_mode; - u8 smf_pg; - - /* For test */ - u32 test_mode; - u32 test_qpc_num; - u32 test_qpc_resvd_num; - u32 test_page_size_reorder; - bool test_xid_alloc_mode; - bool test_gpa_check_enable; - u8 test_qpc_alloc_mode; - u8 test_scqc_alloc_mode; - - u32 test_max_conn_num; - u32 test_max_cache_conn_num; - u32 test_scqc_num; - u32 test_mpt_num; - u32 test_scq_resvd_num; - u32 test_mpt_recvd_num; - u32 test_hash_num; - u32 test_reorder_num; - - u32 max_connect_num; /* PF/VF maximum connection number(1M) */ - /* The maximum connections which can be stick to cache memory, max 1K */ - u16 max_stick2cache_num; - /* Starting address in cache memory for bloom filter, 64Bytes aligned */ - u16 bfilter_start_addr; - /* Length for bloom filter, aligned on 64Bytes. The size is length*64B. - * Bloom filter memory size + 1 must be power of 2. - * The maximum memory size of bloom filter is 4M - */ - u16 bfilter_len; - /* The size of hash bucket tables, align on 64 entries. - * Be used to AND (&) the hash value. Bucket Size +1 must be power of 2. - * The maximum number of hash bucket is 4M - */ - u16 hash_bucket_num; - - struct host_shared_resource_cap shared_res_cap; /* shared capability */ - struct nic_service_cap nic_cap; /* NIC capability */ - struct rdma_service_cap rdma_cap; /* RDMA capability */ - struct fc_service_cap fc_cap; /* FC capability */ - struct toe_service_cap toe_cap; /* ToE capability */ - struct ovs_service_cap ovs_cap; /* OVS capability */ - struct ipsec_service_cap ipsec_cap; /* IPsec capability */ -}; - -struct cfg_eq { - enum sphw_service_type type; - int eqn; - int free; /* 1 - alocated, 0- freed */ -}; - -struct cfg_eq_info { - struct cfg_eq *eq; - - u8 num_ceq; - - u8 num_ceq_remain; - - /* mutex used for allocate EQs */ - struct mutex eq_mutex; -}; - -struct irq_alloc_info_st { - enum sphw_service_type type; - int free; /* 1 - alocated, 0- freed */ - struct irq_info info; -}; - -struct cfg_irq_info { - struct irq_alloc_info_st *alloc_info; - u16 num_total; - u16 num_irq_remain; - u16 num_irq_hw; /* device max irq number */ - - /* mutex used for allocate EQs */ - struct mutex irq_mutex; -}; - -#define VECTOR_THRESHOLD 2 - -struct cfg_mgmt_info { - struct sphw_hwdev *hwdev; - struct service_cap svc_cap; - struct cfg_eq_info eq_info; /* EQ */ - struct cfg_irq_info irq_param_info; /* IRQ */ - u32 func_seq_num; /* temporary */ -}; - -#define IS_NIC_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_NIC_BIT0) -#define IS_ROCE_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_ROCE_BIT1) -#define IS_FCOE_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_FCOE_BIT2) -#define IS_TOE_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_TOE_BIT3) -#define IS_IPSEC_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_IPSEC_BIT4) -#define IS_FC_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_FC_BIT5) -#define IS_FIC_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_FIC_BIT6) -#define IS_OVS_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_OVS_BIT7) -#define IS_ACL_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_ACL_BIT8) -#define IS_IOE_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_IOE_BIT9) -#define IS_FT_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_FT_EN) -#define IS_RDMA_TYPE(dev) \ - (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SVC_RDMA_EN) -#define IS_RDMA_ENABLE(dev) \ - ((dev)->cfg_mgmt->svc_cap.sf_svc_attr.rdma_en) - -int init_cfg_mgmt(struct sphw_hwdev *dev); - -void free_cfg_mgmt(struct sphw_hwdev *dev); - -int init_capability(struct sphw_hwdev *dev); - -void free_capability(struct sphw_hwdev *dev); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.c deleted file mode 100644 index b868bf8ed1cb..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.c +++ /dev/null @@ -1,1280 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/types.h> -#include <linux/delay.h> -#include <linux/module.h> -#include <linux/completion.h> -#include <linux/semaphore.h> -#include <linux/interrupt.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_common.h" -#include "sphw_csr.h" -#include "sphw_hwdev.h" -#include "sphw_hwif.h" -#include "sphw_wq.h" -#include "sphw_cmdq.h" -#include "sphw_comm_msg_intf.h" -#include "sphw_hw_comm.h" - -#define SPHW_MSIX_CNT_LLI_TIMER_SHIFT 0 -#define SPHW_MSIX_CNT_LLI_CREDIT_SHIFT 8 -#define SPHW_MSIX_CNT_COALESC_TIMER_SHIFT 8 -#define SPHW_MSIX_CNT_PENDING_SHIFT 8 -#define SPHW_MSIX_CNT_RESEND_TIMER_SHIFT 29 - -#define SPHW_MSIX_CNT_LLI_TIMER_MASK 0xFFU -#define SPHW_MSIX_CNT_LLI_CREDIT_MASK 0xFFU -#define SPHW_MSIX_CNT_COALESC_TIMER_MASK 0xFFU -#define SPHW_MSIX_CNT_PENDING_MASK 0x1FU -#define SPHW_MSIX_CNT_RESEND_TIMER_MASK 0x7U - -#define SPHW_MSIX_CNT_SET(val, member) \ - (((val) & SPHW_MSIX_CNT_##member##_MASK) << \ - SPHW_MSIX_CNT_##member##_SHIFT) - -#define DEFAULT_RX_BUF_SIZE ((u16)0xB) - -enum sphw_rx_buf_size { - SPHW_RX_BUF_SIZE_32B = 0x20, - SPHW_RX_BUF_SIZE_64B = 0x40, - SPHW_RX_BUF_SIZE_96B = 0x60, - SPHW_RX_BUF_SIZE_128B = 0x80, - SPHW_RX_BUF_SIZE_192B = 0xC0, - SPHW_RX_BUF_SIZE_256B = 0x100, - SPHW_RX_BUF_SIZE_384B = 0x180, - SPHW_RX_BUF_SIZE_512B = 0x200, - SPHW_RX_BUF_SIZE_768B = 0x300, - SPHW_RX_BUF_SIZE_1K = 0x400, - SPHW_RX_BUF_SIZE_1_5K = 0x600, - SPHW_RX_BUF_SIZE_2K = 0x800, - SPHW_RX_BUF_SIZE_3K = 0xC00, - SPHW_RX_BUF_SIZE_4K = 0x1000, - SPHW_RX_BUF_SIZE_8K = 0x2000, - SPHW_RX_BUF_SIZE_16K = 0x4000, -}; - -const int sphw_hw_rx_buf_size[] = { - SPHW_RX_BUF_SIZE_32B, - SPHW_RX_BUF_SIZE_64B, - SPHW_RX_BUF_SIZE_96B, - SPHW_RX_BUF_SIZE_128B, - SPHW_RX_BUF_SIZE_192B, - SPHW_RX_BUF_SIZE_256B, - SPHW_RX_BUF_SIZE_384B, - SPHW_RX_BUF_SIZE_512B, - SPHW_RX_BUF_SIZE_768B, - SPHW_RX_BUF_SIZE_1K, - SPHW_RX_BUF_SIZE_1_5K, - SPHW_RX_BUF_SIZE_2K, - SPHW_RX_BUF_SIZE_3K, - SPHW_RX_BUF_SIZE_4K, - SPHW_RX_BUF_SIZE_8K, - SPHW_RX_BUF_SIZE_16K, -}; - -static inline int comm_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - return sphw_msg_to_mgmt_sync(hwdev, SPHW_MOD_COMM, cmd, buf_in, in_size, buf_out, - out_size, 0, SPHW_CHANNEL_COMM); -} - -static inline int comm_msg_to_mgmt_sync_ch(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u16 channel) -{ - return sphw_msg_to_mgmt_sync(hwdev, SPHW_MOD_COMM, cmd, buf_in, - in_size, buf_out, out_size, 0, channel); -} - -int sphw_get_interrupt_cfg(void *dev, struct interrupt_info *info, u16 channel) -{ - struct sphw_hwdev *hwdev = dev; - struct comm_cmd_msix_config msix_cfg; - u16 out_size = sizeof(msix_cfg); - int err; - - if (!hwdev || !info) - return -EINVAL; - - memset(&msix_cfg, 0, sizeof(msix_cfg)); - msix_cfg.func_id = sphw_global_func_id(hwdev); - msix_cfg.msix_index = info->msix_index; - msix_cfg.opcode = MGMT_MSG_CMD_OP_GET; - - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_CFG_MSIX_CTRL_REG, - &msix_cfg, sizeof(msix_cfg), &msix_cfg, - &out_size, channel); - if (err || !out_size || msix_cfg.head.status) { - sdk_err(hwdev->dev_hdl, "Failed to get interrupt config, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, msix_cfg.head.status, out_size, channel); - return -EINVAL; - } - - info->lli_credit_limit = msix_cfg.lli_credit_cnt; - info->lli_timer_cfg = msix_cfg.lli_timer_cnt; - info->pending_limt = msix_cfg.pending_cnt; - info->coalesc_timer_cfg = msix_cfg.coalesce_timer_cnt; - info->resend_timer_cfg = msix_cfg.resend_timer_cnt; - - return 0; -} - -int sphw_set_interrupt_cfg_direct(void *hwdev, struct interrupt_info *info, u16 channel) -{ - struct comm_cmd_msix_config msix_cfg; - u16 out_size = sizeof(msix_cfg); - int err; - - if (!hwdev) - return -EINVAL; - - memset(&msix_cfg, 0, sizeof(msix_cfg)); - msix_cfg.func_id = sphw_global_func_id(hwdev); - msix_cfg.msix_index = (u16)info->msix_index; - msix_cfg.opcode = MGMT_MSG_CMD_OP_SET; - - msix_cfg.lli_credit_cnt = info->lli_credit_limit; - msix_cfg.lli_timer_cnt = info->lli_timer_cfg; - msix_cfg.pending_cnt = info->pending_limt; - msix_cfg.coalesce_timer_cnt = info->coalesc_timer_cfg; - msix_cfg.resend_timer_cnt = info->resend_timer_cfg; - - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_CFG_MSIX_CTRL_REG, - &msix_cfg, sizeof(msix_cfg), &msix_cfg, - &out_size, channel); - if (err || !out_size || msix_cfg.head.status) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to set interrupt config, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, msix_cfg.head.status, out_size, channel); - return -EINVAL; - } - - return 0; -} - -int sphw_set_interrupt_cfg(void *dev, struct interrupt_info info, u16 channel) -{ - struct interrupt_info temp_info; - struct sphw_hwdev *hwdev = dev; - int err; - - if (!hwdev) - return -EINVAL; - - temp_info.msix_index = info.msix_index; - - err = sphw_get_interrupt_cfg(hwdev, &temp_info, channel); - if (err) - return -EINVAL; - - if (!info.lli_set) { - info.lli_credit_limit = temp_info.lli_credit_limit; - info.lli_timer_cfg = temp_info.lli_timer_cfg; - } - - if (!info.interrupt_coalesc_set) { - info.pending_limt = temp_info.pending_limt; - info.coalesc_timer_cfg = temp_info.coalesc_timer_cfg; - info.resend_timer_cfg = temp_info.resend_timer_cfg; - } - - return sphw_set_interrupt_cfg_direct(hwdev, &info, channel); -} - -void sphw_misx_intr_clear_resend_bit(void *hwdev, u16 msix_idx, u8 clear_resend_en) -{ - struct sphw_hwif *hwif = NULL; - u32 msix_ctrl = 0, addr; - - if (!hwdev) - return; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - msix_ctrl = SPHW_MSI_CLR_INDIR_SET(msix_idx, SIMPLE_INDIR_IDX) | - SPHW_MSI_CLR_INDIR_SET(clear_resend_en, RESEND_TIMER_CLR); - - addr = SPHW_CSR_FUNC_MSI_CLR_WR_ADDR; - sphw_hwif_write_reg(hwif, addr, msix_ctrl); -} - -int sphw_set_wq_page_size(void *hwdev, u16 func_idx, u32 page_size, u16 channel) -{ - struct comm_cmd_wq_page_size page_size_info; - u16 out_size = sizeof(page_size_info); - int err; - - memset(&page_size_info, 0, sizeof(page_size_info)); - page_size_info.func_id = func_idx; - page_size_info.page_size = SPHW_PAGE_SIZE_HW(page_size); - page_size_info.opcode = MGMT_MSG_CMD_OP_SET; - - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_CFG_PAGESIZE, - &page_size_info, sizeof(page_size_info), - &page_size_info, &out_size, channel); - if (err || !out_size || page_size_info.head.status) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, "Failed to set wq page size, err: %d, status: 0x%x, out_size: 0x%0x, channel: 0x%x\n", - err, page_size_info.head.status, out_size, channel); - return -EFAULT; - } - - return 0; -} - -int sphw_func_reset(void *dev, u16 func_id, u64 reset_flag, u16 channel) -{ - struct comm_cmd_func_reset func_reset; - struct sphw_hwdev *hwdev = dev; - u16 out_size = sizeof(func_reset); - int err = 0; - - if (!dev) { - pr_err("Invalid para: dev is null.\n"); - return -EINVAL; - } - - sdk_info(hwdev->dev_hdl, "Function is reset, flag: 0x%llx, channel:0x%x\n", - reset_flag, channel); - - memset(&func_reset, 0, sizeof(func_reset)); - func_reset.func_id = func_id; - func_reset.reset_flag = reset_flag; - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_FUNC_RESET, - &func_reset, sizeof(func_reset), - &func_reset, &out_size, channel); - if (err || !out_size || func_reset.head.status) { - sdk_err(hwdev->dev_hdl, "Failed to reset func resources, reset_flag 0x%llx, err: %d, status: 0x%x, out_size: 0x%x\n", - reset_flag, err, func_reset.head.status, out_size); - return -EIO; - } - - return 0; -} - -static u16 get_hw_rx_buf_size(int rx_buf_sz) -{ - u16 num_hw_types = - sizeof(sphw_hw_rx_buf_size) / - sizeof(sphw_hw_rx_buf_size[0]); - u16 i; - - for (i = 0; i < num_hw_types; i++) { - if (sphw_hw_rx_buf_size[i] == rx_buf_sz) - return i; - } - - pr_err("Chip can't support rx buf size of %d\n", rx_buf_sz); - - return DEFAULT_RX_BUF_SIZE; /* default 2K */ -} - -int sphw_set_root_ctxt(void *hwdev, u32 rq_depth, u32 sq_depth, int rx_buf_sz, u16 channel) -{ - struct comm_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_id = sphw_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 = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_SET_VAT, - &root_ctxt, sizeof(root_ctxt), - &root_ctxt, &out_size, channel); - if (err || !out_size || root_ctxt.head.status) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to set root context, err: %d, status: 0x%x, out_size: 0x%x, channel: 0x%x\n", - err, root_ctxt.head.status, out_size, channel); - return -EFAULT; - } - - return 0; -} - -int sphw_clean_root_ctxt(void *hwdev, u16 channel) -{ - struct comm_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_id = sphw_global_func_id(hwdev); - - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_SET_VAT, - &root_ctxt, sizeof(root_ctxt), - &root_ctxt, &out_size, channel); - if (err || !out_size || root_ctxt.head.status) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to set root context, err: %d, status: 0x%x, out_size: 0x%x, channel: 0x%x\n", - err, root_ctxt.head.status, out_size, channel); - return -EFAULT; - } - - return 0; -} - -int sphw_set_cmdq_depth(void *hwdev, u16 cmdq_depth) -{ - struct comm_cmd_root_ctxt root_ctxt; - u16 out_size = sizeof(root_ctxt); - int err; - - memset(&root_ctxt, 0, sizeof(root_ctxt)); - root_ctxt.func_id = sphw_global_func_id(hwdev); - - root_ctxt.set_cmdq_depth = 1; - root_ctxt.cmdq_depth = (u8)ilog2(cmdq_depth); - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SET_VAT, &root_ctxt, - sizeof(root_ctxt), &root_ctxt, &out_size); - if (err || !out_size || root_ctxt.head.status) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to set cmdq depth, err: %d, status: 0x%x, out_size: 0x%x\n", - err, root_ctxt.head.status, out_size); - return -EFAULT; - } - - return 0; -} - -int sphw_set_cmdq_ctxt(struct sphw_hwdev *hwdev, u8 cmdq_id, struct cmdq_ctxt_info *ctxt) -{ - struct comm_cmd_cmdq_ctxt cmdq_ctxt; - u16 out_size = sizeof(cmdq_ctxt); - int err; - - memset(&cmdq_ctxt, 0, sizeof(cmdq_ctxt)); - memcpy(&cmdq_ctxt.ctxt, ctxt, sizeof(*ctxt)); - cmdq_ctxt.func_id = sphw_global_func_id(hwdev); - cmdq_ctxt.cmdq_id = cmdq_id; - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SET_CMDQ_CTXT, - &cmdq_ctxt, sizeof(cmdq_ctxt), - &cmdq_ctxt, &out_size); - if (err || !out_size || cmdq_ctxt.head.status) { - sdk_err(hwdev->dev_hdl, "Failed to set cmdq ctxt, err: %d, status: 0x%x, out_size: 0x%x\n", - err, cmdq_ctxt.head.status, out_size); - return -EFAULT; - } - - return 0; -} - -int sphw_set_ceq_ctrl_reg(struct sphw_hwdev *hwdev, u16 q_id, u32 ctrl0, u32 ctrl1) -{ - struct comm_cmd_ceq_ctrl_reg ceq_ctrl; - u16 out_size = sizeof(ceq_ctrl); - int err; - - memset(&ceq_ctrl, 0, sizeof(ceq_ctrl)); - ceq_ctrl.func_id = sphw_global_func_id(hwdev); - ceq_ctrl.q_id = q_id; - ceq_ctrl.ctrl0 = ctrl0; - ceq_ctrl.ctrl1 = ctrl1; - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SET_CEQ_CTRL_REG, - &ceq_ctrl, sizeof(ceq_ctrl), - &ceq_ctrl, &out_size); - if (err || !out_size || ceq_ctrl.head.status) { - sdk_err(hwdev->dev_hdl, "Failed to set ceq %u ctrl reg, err: %d status: 0x%x, out_size: 0x%x\n", - q_id, err, ceq_ctrl.head.status, out_size); - return -EFAULT; - } - - return 0; -} - -int sphw_set_dma_attr_tbl(struct sphw_hwdev *hwdev, u8 entry_idx, u8 st, u8 at, u8 ph, - u8 no_snooping, u8 tph_en) -{ - struct comm_cmd_dma_attr_config dma_attr; - u16 out_size = sizeof(dma_attr); - int err; - - memset(&dma_attr, 0, sizeof(dma_attr)); - dma_attr.func_id = sphw_global_func_id(hwdev); - dma_attr.entry_idx = entry_idx; - dma_attr.st = st; - dma_attr.at = at; - dma_attr.ph = ph; - dma_attr.no_snooping = no_snooping; - dma_attr.tph_en = tph_en; - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SET_DMA_ATTR, &dma_attr, sizeof(dma_attr), - &dma_attr, &out_size); - if (err || !out_size || dma_attr.head.status) { - sdk_err(hwdev->dev_hdl, "Failed to set dma_attr, err: %d, status: 0x%x, out_size: 0x%x\n", - err, dma_attr.head.status, out_size); - return -EIO; - } - - return 0; -} - -int sphw_set_bdf_ctxt(void *hwdev, u8 bus, u8 device, u8 function) -{ - struct comm_cmd_bdf_info bdf_info; - u16 out_size = sizeof(bdf_info); - int err; - - if (!hwdev) - return -EINVAL; - - memset(&bdf_info, 0, sizeof(bdf_info)); - bdf_info.function_idx = sphw_global_func_id(hwdev); - bdf_info.bus = bus; - bdf_info.device = device; - bdf_info.function = function; - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SEND_BDF_INFO, - &bdf_info, sizeof(bdf_info), - &bdf_info, &out_size); - if (err || !out_size || bdf_info.head.status) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to set bdf info to MPU, err: %d, status: 0x%x, out_size: 0x%x\n", - err, bdf_info.head.status, out_size); - return -EIO; - } - - return 0; -} - -int sphw_sync_time(void *hwdev, u64 time) -{ - struct comm_cmd_sync_time time_info; - u16 out_size = sizeof(time_info); - int err; - - memset(&time_info, 0, sizeof(time_info)); - time_info.mstime = time; - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SYNC_TIME, &time_info, - sizeof(time_info), &time_info, &out_size); - if (err || time_info.head.status || !out_size) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to sync time to mgmt, err: %d, status: 0x%x, out size: 0x%x\n", - err, time_info.head.status, out_size); - return -EIO; - } - - return 0; -} - -int sphw_get_fw_ver(void *hwdev, enum sphw_fw_ver_type type, u8 *mgmt_ver, - u8 version_size, u16 channel) -{ - struct comm_cmd_get_fw_version fw_ver; - struct sphw_hwdev *dev = hwdev; - u16 out_size = sizeof(fw_ver); - int err; - - if (!hwdev || !mgmt_ver) - return -EINVAL; - - memset(&fw_ver, 0, sizeof(fw_ver)); - fw_ver.fw_type = type; - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_GET_FW_VERSION, - &fw_ver, sizeof(fw_ver), &fw_ver, - &out_size, channel); - if (err || !out_size || fw_ver.head.status) { - sdk_err(dev->dev_hdl, "Failed to get fw version, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, fw_ver.head.status, out_size, channel); - return -EIO; - } - - snprintf(mgmt_ver, version_size, "%s", fw_ver.ver); - - return 0; -} - -int sphw_get_mgmt_version(void *hwdev, u8 *mgmt_ver, u8 version_size, u16 channel) -{ - return sphw_get_fw_ver(hwdev, SPHW_FW_VER_TYPE_MPU, mgmt_ver, version_size, channel); -} - -int sphw_get_fw_version(void *hwdev, struct sphw_fw_version *fw_ver, u16 channel) -{ - int err; - - if (!hwdev || !fw_ver) - return -EINVAL; - - err = sphw_get_fw_ver(hwdev, SPHW_FW_VER_TYPE_MPU, fw_ver->mgmt_ver, - sizeof(fw_ver->mgmt_ver), channel); - if (err) - return err; - - err = sphw_get_fw_ver(hwdev, SPHW_FW_VER_TYPE_NPU, fw_ver->microcode_ver, - sizeof(fw_ver->microcode_ver), channel); - if (err) - return err; - - return sphw_get_fw_ver(hwdev, SPHW_FW_VER_TYPE_BOOT, fw_ver->boot_ver, - sizeof(fw_ver->boot_ver), channel); -} - -static int sphw_comm_features_nego(void *hwdev, u8 opcode, u64 *s_feature, u16 size) -{ - struct comm_cmd_feature_nego feature_nego; - u16 out_size = sizeof(feature_nego); - struct sphw_hwdev *dev = hwdev; - int err; - - if (!hwdev || !s_feature || size > COMM_MAX_FEATURE_QWORD) - return -EINVAL; - - memset(&feature_nego, 0, sizeof(feature_nego)); - feature_nego.func_id = sphw_global_func_id(hwdev); - feature_nego.opcode = opcode; - if (opcode == MGMT_MSG_CMD_OP_SET) - memcpy(feature_nego.s_feature, s_feature, (size * sizeof(u64))); - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_FEATURE_NEGO, - &feature_nego, sizeof(feature_nego), - &feature_nego, &out_size); - if (err || !out_size || feature_nego.head.status) { - sdk_err(dev->dev_hdl, "Failed to negotiate feature, err: %d, status: 0x%x, out size: 0x%x\n", - err, feature_nego.head.status, out_size); - return -EINVAL; - } - - if (opcode == MGMT_MSG_CMD_OP_GET) - memcpy(s_feature, feature_nego.s_feature, (size * sizeof(u64))); - - return 0; -} - -int sphw_get_comm_features(void *hwdev, u64 *s_feature, u16 size) -{ - return sphw_comm_features_nego(hwdev, MGMT_MSG_CMD_OP_GET, s_feature, size); -} - -int sphw_set_comm_features(void *hwdev, u64 *s_feature, u16 size) -{ - return sphw_comm_features_nego(hwdev, MGMT_MSG_CMD_OP_SET, s_feature, size); -} - -int sphw_func_tmr_bitmap_set(void *hwdev, bool en) -{ - struct comm_cmd_func_tmr_bitmap_op bitmap_op; - u16 out_size = sizeof(bitmap_op); - int err; - - if (!hwdev) - return -EINVAL; - - memset(&bitmap_op, 0, sizeof(bitmap_op)); - bitmap_op.func_id = sphw_global_func_id(hwdev); - bitmap_op.opcode = en ? FUNC_TMR_BITMAP_ENABLE : - FUNC_TMR_BITMAP_DISABLE; - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SET_FUNC_TMR_BITMAT, - &bitmap_op, sizeof(bitmap_op), - &bitmap_op, &out_size); - if (err || !out_size || bitmap_op.head.status) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to set timer bitmap, err: %d, status: 0x%x, out_size: 0x%x\n", - err, bitmap_op.head.status, out_size); - return -EFAULT; - } - - return 0; -} - -int ppf_ht_gpa_set(struct sphw_hwdev *hwdev, struct sphw_page_addr *pg0, struct sphw_page_addr *pg1) -{ - struct comm_cmd_ht_gpa ht_gpa_set; - u16 out_size = sizeof(ht_gpa_set); - int ret; - - memset(&ht_gpa_set, 0, sizeof(ht_gpa_set)); - pg0->virt_addr = dma_alloc_coherent(hwdev->dev_hdl, SPHW_HT_GPA_PAGE_SIZE, - &pg0->phys_addr, GFP_KERNEL); - if (!pg0->virt_addr) { - sdk_err(hwdev->dev_hdl, "Alloc pg0 page addr failed\n"); - return -EFAULT; - } - - pg1->virt_addr = dma_alloc_coherent(hwdev->dev_hdl, SPHW_HT_GPA_PAGE_SIZE, - &pg1->phys_addr, GFP_KERNEL); - if (!pg1->virt_addr) { - sdk_err(hwdev->dev_hdl, "Alloc pg1 page addr failed\n"); - return -EFAULT; - } - - ht_gpa_set.host_id = sphw_host_id(hwdev); - ht_gpa_set.page_pa0 = pg0->phys_addr; - ht_gpa_set.page_pa1 = pg1->phys_addr; - sdk_info(hwdev->dev_hdl, "PPF ht gpa set: page_addr0.pa=0x%llx, page_addr1.pa=0x%llx\n", - pg0->phys_addr, pg1->phys_addr); - ret = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SET_PPF_HT_GPA, - &ht_gpa_set, sizeof(ht_gpa_set), - &ht_gpa_set, &out_size); - if (ret || !out_size || ht_gpa_set.head.status) { - sdk_warn(hwdev->dev_hdl, "PPF ht gpa set failed, ret: %d, status: 0x%x, out_size: 0x%x\n", - ret, ht_gpa_set.head.status, out_size); - return -EFAULT; - } - - hwdev->page_pa0.phys_addr = pg0->phys_addr; - hwdev->page_pa0.virt_addr = pg0->virt_addr; - - hwdev->page_pa1.phys_addr = pg1->phys_addr; - hwdev->page_pa1.virt_addr = pg1->virt_addr; - - return 0; -} - -int sphw_ppf_ht_gpa_init(struct sphw_hwdev *hwdev) -{ - int ret; - int i; - int j; - int size; - - struct sphw_page_addr page_addr0[SPHW_PPF_HT_GPA_SET_RETRY_TIMES]; - struct sphw_page_addr page_addr1[SPHW_PPF_HT_GPA_SET_RETRY_TIMES]; - - size = SPHW_PPF_HT_GPA_SET_RETRY_TIMES * sizeof(page_addr0[0]); - memset(page_addr0, 0, size); - memset(page_addr1, 0, size); - - for (i = 0; i < SPHW_PPF_HT_GPA_SET_RETRY_TIMES; i++) { - ret = ppf_ht_gpa_set(hwdev, &page_addr0[i], &page_addr1[i]); - if (!ret) - break; - } - - for (j = 0; j < i; j++) { - if (page_addr0[j].virt_addr) { - dma_free_coherent(hwdev->dev_hdl, - SPHW_HT_GPA_PAGE_SIZE, - page_addr0[j].virt_addr, - page_addr0[j].phys_addr); - page_addr0[j].virt_addr = NULL; - } - if (page_addr1[j].virt_addr) { - dma_free_coherent(hwdev->dev_hdl, - SPHW_HT_GPA_PAGE_SIZE, - page_addr1[j].virt_addr, - page_addr1[j].phys_addr); - page_addr1[j].virt_addr = NULL; - } - } - - if (i >= SPHW_PPF_HT_GPA_SET_RETRY_TIMES) { - sdk_err(hwdev->dev_hdl, "PPF ht gpa init failed, retry times: %d\n", - i); - return -EFAULT; - } - - return 0; -} - -void sphw_ppf_ht_gpa_deinit(struct sphw_hwdev *hwdev) -{ - if (hwdev->page_pa0.virt_addr) { - dma_free_coherent(hwdev->dev_hdl, SPHW_HT_GPA_PAGE_SIZE, - hwdev->page_pa0.virt_addr, - hwdev->page_pa0.phys_addr); - hwdev->page_pa0.virt_addr = NULL; - } - - if (hwdev->page_pa1.virt_addr) { - dma_free_coherent(hwdev->dev_hdl, SPHW_HT_GPA_PAGE_SIZE, - hwdev->page_pa1.virt_addr, - hwdev->page_pa1.phys_addr); - hwdev->page_pa1.virt_addr = NULL; - } -} - -static int set_ppf_tmr_status(struct sphw_hwdev *hwdev, - enum ppf_tmr_status status) -{ - struct comm_cmd_ppf_tmr_op op; - u16 out_size = sizeof(op); - int err = 0; - - if (!hwdev) - return -EINVAL; - - memset(&op, 0, sizeof(op)); - - if (sphw_func_type(hwdev) != TYPE_PPF) - return -EFAULT; - - if (status == SPHW_PPF_TMR_FLAG_START) { - err = sphw_ppf_ht_gpa_init(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "PPF ht gpa init fail!\n"); - return -EFAULT; - } - } else { - sphw_ppf_ht_gpa_deinit(hwdev); - } - - op.opcode = status; - op.ppf_id = sphw_ppf_idx(hwdev); - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SET_PPF_TMR, &op, - sizeof(op), &op, &out_size); - if (err || !out_size || op.head.status) { - sdk_err(hwdev->dev_hdl, "Failed to set ppf timer, err: %d, status: 0x%x, out_size: 0x%x\n", - err, op.head.status, out_size); - return -EFAULT; - } - - return 0; -} - -int sphw_ppf_tmr_start(void *hwdev) -{ - if (!hwdev) { - pr_err("Hwdev pointer is NULL for starting ppf timer\n"); - return -EINVAL; - } - - return set_ppf_tmr_status(hwdev, SPHW_PPF_TMR_FLAG_START); -} - -int sphw_ppf_tmr_stop(void *hwdev) -{ - if (!hwdev) { - pr_err("Hwdev pointer is NULL for stop ppf timer\n"); - return -EINVAL; - } - - return set_ppf_tmr_status(hwdev, SPHW_PPF_TMR_FLAG_STOP); -} - -int mqm_eqm_try_alloc_mem(struct sphw_hwdev *hwdev, u32 page_size, - u32 page_num) -{ - struct sphw_page_addr *page_addr = hwdev->mqm_att.brm_srch_page_addr; - u32 valid_num = 0; - u32 flag = 1; - u32 i = 0; - - for (i = 0; i < page_num; i++) { - page_addr->virt_addr = - dma_alloc_coherent(hwdev->dev_hdl, page_size, - &page_addr->phys_addr, GFP_KERNEL); - if (!page_addr->virt_addr) { - flag = 0; - break; - } - valid_num++; - page_addr++; - } - - if (flag == 1) { - hwdev->mqm_att.page_size = page_size; - hwdev->mqm_att.page_num = page_num; - } else { - page_addr = hwdev->mqm_att.brm_srch_page_addr; - for (i = 0; i < valid_num; i++) { - dma_free_coherent(hwdev->dev_hdl, page_size, - page_addr->virt_addr, - page_addr->phys_addr); - page_addr++; - } - return -EFAULT; - } - - return 0; -} - -int mqm_eqm_alloc_page_mem(struct sphw_hwdev *hwdev) -{ - int ret = 0; - int page_num; - - /* apply for 2M page, page number is chunk_num/1024 */ - page_num = (hwdev->mqm_att.chunk_num + 1023) >> 10; - ret = mqm_eqm_try_alloc_mem(hwdev, 2 * 1024 * 1024, page_num); - if (!ret) { - sdk_info(hwdev->dev_hdl, "[mqm_eqm_init] Alloc page_size 2M OK\n"); - return 0; - } - - /* apply for 64KB page, page number is chunk_num/32 */ - page_num = (hwdev->mqm_att.chunk_num + 31) >> 5; - ret = mqm_eqm_try_alloc_mem(hwdev, 64 * 1024, page_num); - if (!ret) { - sdk_info(hwdev->dev_hdl, "[mqm_eqm_init] Alloc page_size 64K OK\n"); - return 0; - } - - /* apply for 4KB page, page number is chunk_num/2 */ - page_num = (hwdev->mqm_att.chunk_num + 1) >> 1; - ret = mqm_eqm_try_alloc_mem(hwdev, 4 * 1024, page_num); - if (!ret) { - sdk_info(hwdev->dev_hdl, "[mqm_eqm_init] Alloc page_size 4K OK\n"); - return 0; - } - - return ret; -} - -void mqm_eqm_free_page_mem(struct sphw_hwdev *hwdev) -{ - u32 i; - struct sphw_page_addr *page_addr; - u32 page_size; - - page_size = hwdev->mqm_att.page_size; - page_addr = hwdev->mqm_att.brm_srch_page_addr; - - for (i = 0; i < hwdev->mqm_att.page_num; i++) { - dma_free_coherent(hwdev->dev_hdl, page_size, - page_addr->virt_addr, page_addr->phys_addr); - page_addr++; - } -} - -int mqm_eqm_set_cfg_2_hw(struct sphw_hwdev *hwdev, u8 valid) -{ - struct comm_cmd_eqm_cfg info_eqm_cfg; - u16 out_size = sizeof(info_eqm_cfg); - int err; - - memset(&info_eqm_cfg, 0, sizeof(info_eqm_cfg)); - - info_eqm_cfg.host_id = sphw_host_id(hwdev); - info_eqm_cfg.page_size = hwdev->mqm_att.page_size; - info_eqm_cfg.valid = valid; - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_SET_MQM_CFG_INFO, - &info_eqm_cfg, sizeof(info_eqm_cfg), - &info_eqm_cfg, &out_size); - if (err || !out_size || info_eqm_cfg.head.status) { - sdk_err(hwdev->dev_hdl, "Failed to init func table, err: %d, status: 0x%x, out_size: 0x%x\n", - err, info_eqm_cfg.head.status, out_size); - return -EFAULT; - } - - return 0; -} - -#define EQM_DATA_BUF_SIZE 1024 -#define MQM_ATT_PAGE_NUM 128 - -int mqm_eqm_set_page_2_hw(struct sphw_hwdev *hwdev) -{ - struct comm_cmd_eqm_search_gpa *info = NULL; - struct sphw_page_addr *page_addr = NULL; - void *send_buf = NULL; - u16 send_buf_size; - u32 i; - u64 *gpa_hi52 = NULL; - u64 gpa; - u32 num; - u32 start_idx; - int err = 0; - u16 out_size; - u8 cmd; - - send_buf_size = sizeof(struct comm_cmd_eqm_search_gpa) + - EQM_DATA_BUF_SIZE; - send_buf = kzalloc(send_buf_size, GFP_KERNEL); - if (!send_buf) { - sdk_err(hwdev->dev_hdl, "Alloc virtual mem failed\r\n"); - return -EFAULT; - } - - page_addr = hwdev->mqm_att.brm_srch_page_addr; - info = (struct comm_cmd_eqm_search_gpa *)send_buf; - - gpa_hi52 = info->gpa_hi52; - num = 0; - start_idx = 0; - cmd = COMM_MGMT_CMD_SET_MQM_SRCH_GPA; - for (i = 0; i < hwdev->mqm_att.page_num; i++) { - /* gpa align to 4K, save gpa[31:12] */ - gpa = page_addr->phys_addr >> 12; - gpa_hi52[num] = gpa; - num++; - if (num == MQM_ATT_PAGE_NUM) { - info->num = num; - info->start_idx = start_idx; - info->host_id = sphw_host_id(hwdev); - out_size = send_buf_size; - err = comm_msg_to_mgmt_sync(hwdev, cmd, info, - (u16)send_buf_size, - info, &out_size); - if (MSG_TO_MGMT_SYNC_RETURN_ERR(err, out_size, - info->head.status)) { - sdk_err(hwdev->dev_hdl, "Set mqm srch gpa fail, err: %d, status: 0x%x, out_size: 0x%x\n", - err, info->head.status, out_size); - err = -EFAULT; - goto set_page_2_hw_end; - } - - gpa_hi52 = info->gpa_hi52; - num = 0; - start_idx = i + 1; - } - page_addr++; - } - - if (num != 0) { - info->num = num; - info->start_idx = start_idx; - info->host_id = sphw_host_id(hwdev); - out_size = send_buf_size; - err = comm_msg_to_mgmt_sync(hwdev, cmd, info, - (u16)send_buf_size, info, - &out_size); - if (MSG_TO_MGMT_SYNC_RETURN_ERR(err, out_size, - info->head.status)) { - sdk_err(hwdev->dev_hdl, "Set mqm srch gpa fail, err: %d, status: 0x%x, out_size: 0x%x\n", - err, info->head.status, out_size); - err = -EFAULT; - goto set_page_2_hw_end; - } - } - -set_page_2_hw_end: - kfree(send_buf); - return err; -} - -int mqm_eqm_init(struct sphw_hwdev *hwdev) -{ - struct comm_cmd_get_eqm_num info_eqm_fix; - u16 len = sizeof(info_eqm_fix); - int ret; - - if (hwdev->hwif->attr.func_type != TYPE_PPF) - return 0; - - memset(&info_eqm_fix, 0, sizeof(info_eqm_fix)); - - ret = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_GET_MQM_FIX_INFO, - &info_eqm_fix, sizeof(info_eqm_fix), - &info_eqm_fix, &len); - if (ret || !len || info_eqm_fix.head.status) { - sdk_err(hwdev->dev_hdl, "Get mqm fix info fail,err: %d, status: 0x%x, out_size: 0x%x\n", - ret, info_eqm_fix.head.status, len); - return -EFAULT; - } - sdk_info(hwdev->dev_hdl, "get chunk_num: 0x%x, search_gpa_num: 0x%08x\n", - info_eqm_fix.chunk_num, info_eqm_fix.search_gpa_num); - if (!(info_eqm_fix.chunk_num)) - return 0; - - hwdev->mqm_att.chunk_num = info_eqm_fix.chunk_num; - hwdev->mqm_att.search_gpa_num = info_eqm_fix.search_gpa_num; - hwdev->mqm_att.page_size = 0; - hwdev->mqm_att.page_num = 0; - - hwdev->mqm_att.brm_srch_page_addr = - kcalloc(hwdev->mqm_att.chunk_num, - sizeof(struct sphw_page_addr), GFP_KERNEL); - if (!(hwdev->mqm_att.brm_srch_page_addr)) { - sdk_err(hwdev->dev_hdl, "Alloc virtual mem failed\r\n"); - return -EFAULT; - } - - ret = mqm_eqm_alloc_page_mem(hwdev); - if (ret) { - sdk_err(hwdev->dev_hdl, "Alloc eqm page mem failed\r\n"); - goto err_page; - } - - ret = mqm_eqm_set_page_2_hw(hwdev); - if (ret) { - sdk_err(hwdev->dev_hdl, "Set page to hw failed\r\n"); - goto err_ecmd; - } - - ret = mqm_eqm_set_cfg_2_hw(hwdev, 1); - if (ret) { - sdk_err(hwdev->dev_hdl, "Set page to hw failed\r\n"); - goto err_ecmd; - } - - return 0; - -err_ecmd: - mqm_eqm_free_page_mem(hwdev); - -err_page: - kfree(hwdev->mqm_att.brm_srch_page_addr); - - return ret; -} - -void mqm_eqm_deinit(struct sphw_hwdev *hwdev) -{ - int ret; - - if (hwdev->hwif->attr.func_type != TYPE_PPF) - return; - - if (!(hwdev->mqm_att.chunk_num)) - return; - - mqm_eqm_free_page_mem(hwdev); - kfree(hwdev->mqm_att.brm_srch_page_addr); - - ret = mqm_eqm_set_cfg_2_hw(hwdev, 0); - if (ret) { - sdk_err(hwdev->dev_hdl, "Set mqm eqm cfg to chip fail! err: %d\n", - ret); - return; - } - - hwdev->mqm_att.chunk_num = 0; - hwdev->mqm_att.search_gpa_num = 0; - hwdev->mqm_att.page_num = 0; - hwdev->mqm_att.page_size = 0; -} - -int sphw_ppf_ext_db_init(void *dev) -{ - struct sphw_hwdev *hwdev = dev; - int ret; - - /* IS OVS MODE SURPORT EXT DB NEEDED */ - - ret = mqm_eqm_init(hwdev); - if (ret) { - sdk_err(hwdev->dev_hdl, "MQM eqm init fail!\n"); - return -EFAULT; - } - sdk_info(hwdev->dev_hdl, "ppf_ext_db_init ok\r\n"); - - return 0; -} - -int sphw_ppf_ext_db_deinit(void *dev) -{ - struct sphw_hwdev *hwdev = dev; - - if (!dev) - return -EINVAL; - - if (hwdev->hwif->attr.func_type != TYPE_PPF) - return 0; - - mqm_eqm_deinit(hwdev); - - return 0; -} - -#define SPHW_FLR_TIMEOUT 1000 - -static enum sphw_wait_return check_flr_finish_handler(void *priv_data) -{ - struct sphw_hwif *hwif = priv_data; - enum sphw_pf_status status; - - status = sphw_get_pf_status(hwif); - if (status == SPHW_PF_STATUS_FLR_FINISH_FLAG) { - sphw_set_pf_status(hwif, SPHW_PF_STATUS_ACTIVE_FLAG); - return WAIT_PROCESS_CPL; - } - - return WAIT_PROCESS_WAITING; -} - -static int wait_for_flr_finish(struct sphw_hwif *hwif) -{ - return sphw_wait_for_timeout(hwif, check_flr_finish_handler, - SPHW_FLR_TIMEOUT, 10 * USEC_PER_MSEC); -} - -#define SPHW_WAIT_CMDQ_IDLE_TIMEOUT 5000 - -static enum sphw_wait_return check_cmdq_stop_handler(void *priv_data) -{ - struct sphw_hwdev *hwdev = priv_data; - struct sphw_cmdqs *cmdqs = hwdev->cmdqs; - enum sphw_cmdq_type cmdq_type; - - /* Stop waiting when card unpresent */ - if (!hwdev->chip_present_flag) - return WAIT_PROCESS_CPL; - - cmdq_type = SPHW_CMDQ_SYNC; - for (; cmdq_type < SPHW_MAX_CMDQ_TYPES; cmdq_type++) { - if (!sphw_cmdq_idle(&cmdqs->cmdq[cmdq_type])) - return WAIT_PROCESS_WAITING; - } - - return WAIT_PROCESS_CPL; -} - -static int wait_cmdq_stop(struct sphw_hwdev *hwdev) -{ - enum sphw_cmdq_type cmdq_type; - struct sphw_cmdqs *cmdqs = hwdev->cmdqs; - int err; - - if (!(cmdqs->status & SPHW_CMDQ_ENABLE)) - return 0; - - cmdqs->status &= ~SPHW_CMDQ_ENABLE; - - err = sphw_wait_for_timeout(hwdev, check_cmdq_stop_handler, - SPHW_WAIT_CMDQ_IDLE_TIMEOUT, USEC_PER_MSEC); - if (!err) - return 0; - - cmdq_type = SPHW_CMDQ_SYNC; - for (; cmdq_type < SPHW_MAX_CMDQ_TYPES; cmdq_type++) { - if (!sphw_cmdq_idle(&cmdqs->cmdq[cmdq_type])) - sdk_err(hwdev->dev_hdl, "Cmdq %d is busy\n", cmdq_type); - } - - cmdqs->status |= SPHW_CMDQ_ENABLE; - - return err; -} - -static int sphw_pf_rx_tx_flush(struct sphw_hwdev *hwdev, u16 channel) -{ - struct sphw_hwif *hwif = hwdev->hwif; - struct comm_cmd_clear_doorbell clear_db; - struct comm_cmd_clear_resource clr_res; - u16 out_size; - int err; - int ret = 0; - - /*wait ucode stop I/O */ - msleep(100); - - err = wait_cmdq_stop(hwdev); - if (err) { - sdk_warn(hwdev->dev_hdl, "CMDQ is still working, please check CMDQ timeout value is reasonable\n"); - ret = err; - } - - sphw_disable_doorbell(hwif); - - out_size = sizeof(clear_db); - memset(&clear_db, 0, sizeof(clear_db)); - clear_db.func_id = SPHW_HWIF_GLOBAL_IDX(hwif); - - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_FLUSH_DOORBELL, - &clear_db, sizeof(clear_db), - &clear_db, &out_size, channel); - if (err || !out_size || clear_db.head.status) { - sdk_warn(hwdev->dev_hdl, "Failed to flush doorbell, err: %d, status: 0x%x, out_size: 0x%x, channel: 0x%x\n", - err, clear_db.head.status, out_size, channel); - if (err) - ret = err; - else - ret = -EFAULT; - } - - sphw_set_pf_status(hwif, SPHW_PF_STATUS_FLR_START_FLAG); - - memset(&clr_res, 0, sizeof(clr_res)); - clr_res.func_id = SPHW_HWIF_GLOBAL_IDX(hwif); - - err = sphw_msg_to_mgmt_no_ack(hwdev, SPHW_MOD_COMM, COMM_MGMT_CMD_START_FLUSH, &clr_res, - sizeof(clr_res), channel); - if (err) { - sdk_warn(hwdev->dev_hdl, "Failed to notice flush message, err: %d, channel: 0x%x\n", - err, channel); - ret = err; - } - - err = wait_for_flr_finish(hwif); - if (err) { - sdk_warn(hwdev->dev_hdl, "Wait firmware FLR timeout\n"); - ret = err; - } - - sphw_enable_doorbell(hwif); - - err = sphw_reinit_cmdq_ctxts(hwdev); - if (err) { - sdk_warn(hwdev->dev_hdl, "Failed to reinit cmdq\n"); - ret = err; - } - - return ret; -} - -int sphw_func_rx_tx_flush(void *hwdev, u16 channel) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) - return -EINVAL; - - if (!dev->chip_present_flag) - return 0; - - if (SPHW_FUNC_TYPE(dev) == TYPE_VF) - /* TO DO */ - return 0; - else - return sphw_pf_rx_tx_flush(dev, channel); -} - -int sphw_get_board_info(void *hwdev, struct sphw_board_info *info, u16 channel) -{ - struct comm_cmd_board_info board_info; - u16 out_size = sizeof(board_info); - int err; - - if (!hwdev || !info) - return -EINVAL; - - memset(&board_info, 0, sizeof(board_info)); - err = comm_msg_to_mgmt_sync_ch(hwdev, COMM_MGMT_CMD_GET_BOARD_INFO, - &board_info, sizeof(board_info), - &board_info, &out_size, channel); - if (err || board_info.head.status || !out_size) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to get board info, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, board_info.head.status, out_size, channel); - return -EIO; - } - - memcpy(info, &board_info.info, sizeof(*info)); - - return 0; -} - -int sphw_get_global_attr(void *hwdev, struct comm_global_attr *attr) -{ - struct comm_cmd_get_glb_attr get_attr; - u16 out_size = sizeof(get_attr); - int err = 0; - - err = comm_msg_to_mgmt_sync(hwdev, COMM_MGMT_CMD_GET_GLOBAL_ATTR, - &get_attr, sizeof(get_attr), &get_attr, - &out_size); - if (err || !out_size || get_attr.head.status) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "Failed to get global attribute, err: %d, status: 0x%x, out size: 0x%x\n", - err, get_attr.head.status, out_size); - return -EIO; - } - - memcpy(attr, &get_attr.attr, sizeof(*attr)); - - return 0; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.h deleted file mode 100644 index 4e0cf2dfb21e..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_comm.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_HW_COMM_H -#define SPHW_HW_COMM_H - -#include "sphw_comm_msg_intf.h" - -#define MSG_TO_MGMT_SYNC_RETURN_ERR(err, out_size, status) \ - ((err) || (status) || !(out_size)) - -#define SPHW_PAGE_SIZE_HW(pg_size) ((u8)ilog2((u32)((pg_size) >> 12))) - -enum func_tmr_bitmap_status { - FUNC_TMR_BITMAP_DISABLE, - FUNC_TMR_BITMAP_ENABLE, -}; - -enum ppf_tmr_status { - SPHW_PPF_TMR_FLAG_STOP, - SPHW_PPF_TMR_FLAG_START, -}; - -#define SPHW_HT_GPA_PAGE_SIZE 4096UL -#define SPHW_PPF_HT_GPA_SET_RETRY_TIMES 10 - -int sphw_set_cmdq_depth(void *hwdev, u16 cmdq_depth); - -int sphw_set_cmdq_ctxt(struct sphw_hwdev *hwdev, u8 cmdq_id, struct cmdq_ctxt_info *ctxt); - -int sphw_ppf_ext_db_init(void *dev); - -int sphw_ppf_ext_db_deinit(void *dev); - -int sphw_set_ceq_ctrl_reg(struct sphw_hwdev *hwdev, u16 q_id, u32 ctrl0, u32 ctrl1); - -int sphw_set_dma_attr_tbl(struct sphw_hwdev *hwdevm, u8 entry_idx, u8 st, u8 at, u8 ph, - u8 no_snooping, u8 tph_en); - -int sphw_get_comm_features(void *hwdev, u64 *s_feature, u16 size); -int sphw_set_comm_features(void *hwdev, u64 *s_feature, u16 size); - -int sphw_get_global_attr(void *hwdev, struct comm_global_attr *attr); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwdev.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwdev.c deleted file mode 100644 index 783fa46bcfe5..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwdev.c +++ /dev/null @@ -1,1324 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/time.h> -#include <linux/timex.h> -#include <linux/rtc.h> -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/types.h> -#include <linux/module.h> -#include <linux/completion.h> -#include <linux/semaphore.h> -#include <linux/interrupt.h> -#include <linux/vmalloc.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_common.h" -#include "sphw_hwdev.h" -#include "sphw_csr.h" -#include "sphw_hwif.h" -#include "sphw_eqs.h" -#include "sphw_api_cmd.h" -#include "sphw_mgmt.h" -#include "sphw_mbox.h" -#include "sphw_wq.h" -#include "sphw_cmdq.h" -#include "sphw_hw_cfg.h" -#include "sphw_hw_comm.h" -#include "sphw_prof_adap.h" - -static bool disable_stateful_load; -module_param(disable_stateful_load, bool, 0444); -MODULE_PARM_DESC(disable_stateful_load, "Disable stateful load - default is false"); - -static bool disable_cfg_comm; -module_param(disable_cfg_comm, bool, 0444); -MODULE_PARM_DESC(disable_cfg_comm, "disable_cfg_comm or not - default is false"); - -static unsigned int wq_page_order = SPHW_MAX_WQ_PAGE_SIZE_ORDER; -module_param(wq_page_order, uint, 0444); -MODULE_PARM_DESC(wq_page_order, "Set wq page size order, wq page size is 4K * (2 ^ wq_page_order) - default is 8"); - -enum sphw_pcie_nosnoop { - SPHW_PCIE_SNOOP = 0, - SPHW_PCIE_NO_SNOOP = 1, -}; - -enum sphw_pcie_tph { - SPHW_PCIE_TPH_DISABLE = 0, - SPHW_PCIE_TPH_ENABLE = 1, -}; - -#define SPHW_DMA_ATTR_INDIR_IDX_SHIFT 0 - -#define SPHW_DMA_ATTR_INDIR_IDX_MASK 0x3FF - -#define SPHW_DMA_ATTR_INDIR_IDX_SET(val, member) \ - (((u32)(val) & SPHW_DMA_ATTR_INDIR_##member##_MASK) << \ - SPHW_DMA_ATTR_INDIR_##member##_SHIFT) - -#define SPHW_DMA_ATTR_INDIR_IDX_CLEAR(val, member) \ - ((val) & (~(SPHW_DMA_ATTR_INDIR_##member##_MASK \ - << SPHW_DMA_ATTR_INDIR_##member##_SHIFT))) - -#define SPHW_DMA_ATTR_ENTRY_ST_SHIFT 0 -#define SPHW_DMA_ATTR_ENTRY_AT_SHIFT 8 -#define SPHW_DMA_ATTR_ENTRY_PH_SHIFT 10 -#define SPHW_DMA_ATTR_ENTRY_NO_SNOOPING_SHIFT 12 -#define SPHW_DMA_ATTR_ENTRY_TPH_EN_SHIFT 13 - -#define SPHW_DMA_ATTR_ENTRY_ST_MASK 0xFF -#define SPHW_DMA_ATTR_ENTRY_AT_MASK 0x3 -#define SPHW_DMA_ATTR_ENTRY_PH_MASK 0x3 -#define SPHW_DMA_ATTR_ENTRY_NO_SNOOPING_MASK 0x1 -#define SPHW_DMA_ATTR_ENTRY_TPH_EN_MASK 0x1 - -#define SPHW_DMA_ATTR_ENTRY_SET(val, member) \ - (((u32)(val) & SPHW_DMA_ATTR_ENTRY_##member##_MASK) << \ - SPHW_DMA_ATTR_ENTRY_##member##_SHIFT) - -#define SPHW_DMA_ATTR_ENTRY_CLEAR(val, member) \ - ((val) & (~(SPHW_DMA_ATTR_ENTRY_##member##_MASK \ - << SPHW_DMA_ATTR_ENTRY_##member##_SHIFT))) - -#define SPHW_PCIE_ST_DISABLE 0 -#define SPHW_PCIE_AT_DISABLE 0 -#define SPHW_PCIE_PH_DISABLE 0 - -#define PCIE_MSIX_ATTR_ENTRY 0 - -#define SPHW_CHIP_PRESENT 1 -#define SPHW_CHIP_ABSENT 0 - -#define SPHW_DEAULT_EQ_MSIX_PENDING_LIMIT 0 -#define SPHW_DEAULT_EQ_MSIX_COALESC_TIMER_CFG 0xFF -#define SPHW_DEAULT_EQ_MSIX_RESEND_TIMER_CFG 7 - -#define SPHW_HWDEV_WQ_NAME "sphw_hardware" -#define SPHW_WQ_MAX_REQ 10 - -static void sphw_init_heartbeat_detect(struct sphw_hwdev *hwdev); -static void sphw_destroy_heartbeat_detect(struct sphw_hwdev *hwdev); - -typedef void (*mgmt_event_cb)(void *handle, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size); - -struct mgmt_event_handle { - u16 cmd; - mgmt_event_cb proc; -}; - -int pf_handle_vf_comm_mbox(void *handle, void *pri_handle, - u16 vf_id, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size) -{ - struct sphw_hwdev *hwdev = handle; - - if (!hwdev) - return -EINVAL; - - sdk_warn(hwdev->dev_hdl, "Unsupported vf mbox event %u to process\n", - cmd); - - return 0; -} - -int vf_handle_pf_comm_mbox(void *handle, void *pri_handle, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size) -{ - struct sphw_hwdev *hwdev = handle; - - if (!hwdev) - return -EINVAL; - - sdk_warn(hwdev->dev_hdl, "Unsupported pf mbox event %u to process\n", - cmd); - return 0; -} - -static void chip_fault_show(struct sphw_hwdev *hwdev, struct sphw_fault_event *event) -{ - char fault_level[FAULT_LEVEL_MAX][FAULT_SHOW_STR_LEN + 1] = { - "fatal", "reset", "host", "flr", "general", "suggestion"}; - char level_str[FAULT_SHOW_STR_LEN + 1]; - u8 level; - - memset(level_str, 0, FAULT_SHOW_STR_LEN + 1); - level = event->event.chip.err_level; - if (level < FAULT_LEVEL_MAX) - strncpy(level_str, fault_level[level], - FAULT_SHOW_STR_LEN); - else - strncpy(level_str, "Unknown", FAULT_SHOW_STR_LEN); - - if (level == FAULT_LEVEL_SERIOUS_FLR) - dev_err(hwdev->dev_hdl, "err_level: %u [%s], flr func_id: %u\n", - level, level_str, event->event.chip.func_id); - - dev_err(hwdev->dev_hdl, "Module_id: 0x%x, err_type: 0x%x, err_level: %u[%s], err_csr_addr: 0x%08x, err_csr_value: 0x%08x\n", - event->event.chip.node_id, - event->event.chip.err_type, level, level_str, - event->event.chip.err_csr_addr, - event->event.chip.err_csr_value); -} - -static void fault_report_show(struct sphw_hwdev *hwdev, - struct sphw_fault_event *event) -{ - char fault_type[FAULT_TYPE_MAX][FAULT_SHOW_STR_LEN + 1] = { - "chip", "ucode", "mem rd timeout", "mem wr timeout", - "reg rd timeout", "reg wr timeout", "phy fault" - }; - char type_str[FAULT_SHOW_STR_LEN + 1]; - struct fault_event_stats *fault = NULL; - - sdk_err(hwdev->dev_hdl, "Fault event report received, func_id: %u\n", - sphw_global_func_id(hwdev)); - - memset(type_str, 0, FAULT_SHOW_STR_LEN + 1); - if (event->type < FAULT_TYPE_MAX) - strncpy(type_str, fault_type[event->type], - strlen(fault_type[event->type])); - else - strncpy(type_str, "Unknown", strlen("Unknown")); - - sdk_err(hwdev->dev_hdl, "Fault type: %u [%s]\n", event->type, type_str); - /* 0, 1, 2 and 3 word Represents array event->event.val index */ - sdk_err(hwdev->dev_hdl, "Fault val[0]: 0x%08x, val[1]: 0x%08x, val[2]: 0x%08x, val[3]: 0x%08x\n", - event->event.val[0], event->event.val[1], event->event.val[2], - event->event.val[3]); - - fault = &hwdev->hw_stats.fault_event_stats; - - switch (event->type) { - case FAULT_TYPE_CHIP: - chip_fault_show(hwdev, event); - break; - case FAULT_TYPE_UCODE: - atomic_inc(&fault->fault_type_stat[event->type]); - sdk_err(hwdev->dev_hdl, "Cause_id: %u, core_id: %u, c_id: %u, epc: 0x%08x\n", - event->event.ucode.cause_id, event->event.ucode.core_id, - event->event.ucode.c_id, event->event.ucode.epc); - break; - case FAULT_TYPE_MEM_RD_TIMEOUT: - case FAULT_TYPE_MEM_WR_TIMEOUT: - atomic_inc(&fault->fault_type_stat[event->type]); - sdk_err(hwdev->dev_hdl, "Err_csr_ctrl: 0x%08x, err_csr_data: 0x%08x, ctrl_tab: 0x%08x, mem_index: 0x%08x\n", - event->event.mem_timeout.err_csr_ctrl, - event->event.mem_timeout.err_csr_data, - event->event.mem_timeout.ctrl_tab, - event->event.mem_timeout.mem_index); - break; - case FAULT_TYPE_REG_RD_TIMEOUT: - case FAULT_TYPE_REG_WR_TIMEOUT: - atomic_inc(&fault->fault_type_stat[event->type]); - sdk_err(hwdev->dev_hdl, "Err_csr: 0x%08x\n", - event->event.reg_timeout.err_csr); - break; - case FAULT_TYPE_PHY_FAULT: - atomic_inc(&fault->fault_type_stat[event->type]); - sdk_err(hwdev->dev_hdl, "Op_type: %u, port_id: %u, dev_ad: %u, csr_addr: 0x%08x, op_data: 0x%08x\n", - event->event.phy_fault.op_type, - event->event.phy_fault.port_id, - event->event.phy_fault.dev_ad, - event->event.phy_fault.csr_addr, - event->event.phy_fault.op_data); - break; - default: - break; - } -} - -static void fault_event_handler(void *dev, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct sphw_cmd_fault_event *fault_event = NULL; - struct sphw_event_info event_info; - struct sphw_hwdev *hwdev = dev; - u8 fault_src = SPHW_FAULT_SRC_TYPE_MAX; - u8 fault_level; - - if (in_size != sizeof(*fault_event)) { - sdk_err(hwdev->dev_hdl, "Invalid fault event report, length: %u, should be %ld\n", - in_size, sizeof(*fault_event)); - return; - } - - fault_event = buf_in; - fault_report_show(hwdev, &fault_event->event); - - if (fault_event->event.type == FAULT_TYPE_CHIP) - fault_level = fault_event->event.event.chip.err_level; - else - fault_level = FAULT_LEVEL_FATAL; - - if (hwdev->event_callback) { - event_info.type = SPHW_EVENT_FAULT; - memcpy(&event_info.info, &fault_event->event, - sizeof(struct sphw_fault_event)); - event_info.info.fault_level = fault_level; - hwdev->event_callback(hwdev->event_pri_handle, &event_info); - } - - if (fault_event->event.type <= FAULT_TYPE_REG_WR_TIMEOUT) - fault_src = fault_event->event.type; - else if (fault_event->event.type == FAULT_TYPE_PHY_FAULT) - fault_src = SPHW_FAULT_SRC_HW_PHY_FAULT; - - sphw_fault_post_process(hwdev, fault_src, fault_level); -} - -static void ffm_event_msg_handler(void *hwdev, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct ffm_intr_info *intr = NULL; - struct sphw_hwdev *dev = hwdev; - - if (in_size != sizeof(*intr)) { - sdk_err(dev->dev_hdl, "Invalid fault event report, length: %u, should be %ld.\n", - in_size, sizeof(*intr)); - return; - } - - intr = buf_in; - - sdk_err(dev->dev_hdl, "node_id: 0x%x, err_type: 0x%x, err_level: %u, err_csr_addr: 0x%08x, err_csr_value: 0x%08x\n", - intr->node_id, intr->err_type, intr->err_level, - intr->err_csr_addr, intr->err_csr_value); -} - -const struct mgmt_event_handle mgmt_event_proc[] = { - { - .cmd = COMM_MGMT_CMD_FAULT_REPORT, - .proc = fault_event_handler, - }, - - { - .cmd = COMM_MGMT_CMD_FFM_SET, - .proc = ffm_event_msg_handler, - }, -}; - -void pf_handle_mgmt_comm_event(void *handle, void *pri_handle, u16 cmd, - void *buf_in, u16 in_size, void *buf_out, - u16 *out_size) -{ - struct sphw_hwdev *hwdev = handle; - u32 i, event_num = ARRAY_LEN(mgmt_event_proc); - - if (!hwdev) - return; - - for (i = 0; i < event_num; i++) { - if (cmd == mgmt_event_proc[i].cmd) { - if (mgmt_event_proc[i].proc) - mgmt_event_proc[i].proc(handle, buf_in, in_size, - buf_out, out_size); - - return; - } - } - - sdk_warn(hwdev->dev_hdl, "Unsupported mgmt cpu event %u to process\n", - cmd); -} - -void sphw_set_chip_present(void *hwdev) -{ - ((struct sphw_hwdev *)hwdev)->chip_present_flag = SPHW_CHIP_PRESENT; -} - -void sphw_set_chip_absent(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - sdk_err(dev->dev_hdl, "Card not present\n"); - dev->chip_present_flag = SPHW_CHIP_ABSENT; -} - -int sphw_get_chip_present_flag(const void *hwdev) -{ - if (!hwdev) - return 0; - - return ((struct sphw_hwdev *)hwdev)->chip_present_flag; -} - -/* TODO */ -void sphw_force_complete_all(void *hwdev) -{ -} - -void sphw_detect_hw_present(void *hwdev) -{ - u32 addr, attr1; - - addr = SPHW_CSR_FUNC_ATTR1_ADDR; - attr1 = sphw_hwif_read_reg(((struct sphw_hwdev *)hwdev)->hwif, addr); - if (attr1 == SPHW_PCIE_LINK_DOWN) { - sphw_set_chip_absent(hwdev); - sphw_force_complete_all(hwdev); - } -} - -/** - * dma_attr_table_init - initialize the default dma attributes - * @hwdev: the pointer to hw device - **/ -static int dma_attr_table_init(struct sphw_hwdev *hwdev) -{ - u32 addr, val, dst_attr; - - /* Use indirect access should set entry_idx first*/ - addr = SPHW_CSR_DMA_ATTR_INDIR_IDX_ADDR; - val = sphw_hwif_read_reg(hwdev->hwif, addr); - val = SPHW_DMA_ATTR_INDIR_IDX_CLEAR(val, IDX); - - val |= SPHW_DMA_ATTR_INDIR_IDX_SET(PCIE_MSIX_ATTR_ENTRY, IDX); - - sphw_hwif_write_reg(hwdev->hwif, addr, val); - - wmb(); /* write index before config */ - - addr = SPHW_CSR_DMA_ATTR_TBL_ADDR; - val = sphw_hwif_read_reg(hwdev->hwif, addr); - dst_attr = SPHW_DMA_ATTR_ENTRY_SET(SPHW_PCIE_ST_DISABLE, ST) | - SPHW_DMA_ATTR_ENTRY_SET(SPHW_PCIE_AT_DISABLE, AT) | - SPHW_DMA_ATTR_ENTRY_SET(SPHW_PCIE_PH_DISABLE, PH) | - SPHW_DMA_ATTR_ENTRY_SET(SPHW_PCIE_SNOOP, NO_SNOOPING) | - SPHW_DMA_ATTR_ENTRY_SET(SPHW_PCIE_TPH_DISABLE, TPH_EN); - if (dst_attr == val) - return 0; - - return sphw_set_dma_attr_tbl(hwdev, PCIE_MSIX_ATTR_ENTRY, SPHW_PCIE_ST_DISABLE, - SPHW_PCIE_AT_DISABLE, SPHW_PCIE_PH_DISABLE, - SPHW_PCIE_SNOOP, SPHW_PCIE_TPH_DISABLE); -} - -static int init_aeqs_msix_attr(struct sphw_hwdev *hwdev) -{ - struct sphw_aeqs *aeqs = hwdev->aeqs; - struct interrupt_info info = {0}; - struct sphw_eq *eq = NULL; - int q_id; - int err; - - info.lli_set = 0; - info.interrupt_coalesc_set = 1; - info.pending_limt = SPHW_DEAULT_EQ_MSIX_PENDING_LIMIT; - info.coalesc_timer_cfg = SPHW_DEAULT_EQ_MSIX_COALESC_TIMER_CFG; - info.resend_timer_cfg = SPHW_DEAULT_EQ_MSIX_RESEND_TIMER_CFG; - - for (q_id = aeqs->num_aeqs - 1; q_id >= 0; q_id--) { - eq = &aeqs->aeq[q_id]; - info.msix_index = eq->eq_irq.msix_entry_idx; - err = sphw_set_interrupt_cfg_direct(hwdev, &info, SPHW_CHANNEL_COMM); - if (err) { - sdk_err(hwdev->dev_hdl, "Set msix attr for aeq %d failed\n", - q_id); - return -EFAULT; - } - } - - return 0; -} - -static int init_ceqs_msix_attr(struct sphw_hwdev *hwdev) -{ - struct sphw_ceqs *ceqs = hwdev->ceqs; - struct interrupt_info info = {0}; - struct sphw_eq *eq = NULL; - u16 q_id; - int err; - - info.lli_set = 0; - info.interrupt_coalesc_set = 1; - info.pending_limt = SPHW_DEAULT_EQ_MSIX_PENDING_LIMIT; - info.coalesc_timer_cfg = SPHW_DEAULT_EQ_MSIX_COALESC_TIMER_CFG; - info.resend_timer_cfg = SPHW_DEAULT_EQ_MSIX_RESEND_TIMER_CFG; - - for (q_id = 0; q_id < ceqs->num_ceqs; q_id++) { - eq = &ceqs->ceq[q_id]; - info.msix_index = eq->eq_irq.msix_entry_idx; - err = sphw_set_interrupt_cfg(hwdev, info, SPHW_CHANNEL_COMM); - if (err) { - sdk_err(hwdev->dev_hdl, "Set msix attr for ceq %u failed\n", - q_id); - return -EFAULT; - } - } - - return 0; -} - -static int sphw_comm_aeqs_init(struct sphw_hwdev *hwdev) -{ - struct irq_info aeq_irqs[SPHW_MAX_AEQS] = {{0} }; - u16 num_aeqs, resp_num_irq = 0, i; - int err; - - num_aeqs = SPHW_HWIF_NUM_AEQS(hwdev->hwif); - if (num_aeqs > SPHW_MAX_AEQS) { - sdk_warn(hwdev->dev_hdl, "Adjust aeq num to %d\n", - SPHW_MAX_AEQS); - num_aeqs = SPHW_MAX_AEQS; - } - err = sphw_alloc_irqs(hwdev, SERVICE_T_INTF, num_aeqs, aeq_irqs, &resp_num_irq); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to alloc aeq irqs, num_aeqs: %u\n", - num_aeqs); - return err; - } - - if (resp_num_irq < num_aeqs) { - sdk_warn(hwdev->dev_hdl, "Adjust aeq num to %u\n", - resp_num_irq); - num_aeqs = resp_num_irq; - } - - err = sphw_aeqs_init(hwdev, num_aeqs, aeq_irqs); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init aeqs\n"); - goto aeqs_init_err; - } - - return 0; - -aeqs_init_err: - for (i = 0; i < num_aeqs; i++) - sphw_free_irq(hwdev, SERVICE_T_INTF, aeq_irqs[i].irq_id); - - return err; -} - -static void sphw_comm_aeqs_free(struct sphw_hwdev *hwdev) -{ - struct irq_info aeq_irqs[SPHW_MAX_AEQS] = {{0} }; - u16 num_irqs, i; - - sphw_get_aeq_irqs(hwdev, aeq_irqs, &num_irqs); - - sphw_aeqs_free(hwdev); - - for (i = 0; i < num_irqs; i++) - sphw_free_irq(hwdev, SERVICE_T_INTF, aeq_irqs[i].irq_id); -} - -static int sphw_comm_ceqs_init(struct sphw_hwdev *hwdev) -{ - struct irq_info ceq_irqs[SPHW_MAX_CEQS] = {{0} }; - u16 num_ceqs, resp_num_irq = 0, i; - int err; - - num_ceqs = SPHW_HWIF_NUM_CEQS(hwdev->hwif); - if (num_ceqs > SPHW_MAX_CEQS) { - sdk_warn(hwdev->dev_hdl, "Adjust ceq num to %d\n", - SPHW_MAX_CEQS); - num_ceqs = SPHW_MAX_CEQS; - } - - err = sphw_alloc_irqs(hwdev, SERVICE_T_INTF, num_ceqs, ceq_irqs, &resp_num_irq); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to alloc ceq irqs, num_ceqs: %u\n", - num_ceqs); - return err; - } - - if (resp_num_irq < num_ceqs) { - sdk_warn(hwdev->dev_hdl, "Adjust ceq num to %u\n", - resp_num_irq); - num_ceqs = resp_num_irq; - } - - err = sphw_ceqs_init(hwdev, num_ceqs, ceq_irqs); - if (err) { - sdk_err(hwdev->dev_hdl, - "Failed to init ceqs, err:%d\n", err); - goto ceqs_init_err; - } - - return 0; - -ceqs_init_err: - for (i = 0; i < num_ceqs; i++) - sphw_free_irq(hwdev, SERVICE_T_INTF, ceq_irqs[i].irq_id); - - return err; -} - -static void sphw_comm_ceqs_free(struct sphw_hwdev *hwdev) -{ - struct irq_info ceq_irqs[SPHW_MAX_CEQS] = {{0} }; - u16 num_irqs; - int i; - - sphw_get_ceq_irqs(hwdev, ceq_irqs, &num_irqs); - - sphw_ceqs_free(hwdev); - - for (i = 0; i < num_irqs; i++) - sphw_free_irq(hwdev, SERVICE_T_INTF, ceq_irqs[i].irq_id); -} - -static int sphw_comm_func_to_func_init(struct sphw_hwdev *hwdev) -{ - int err; - - err = sphw_func_to_func_init(hwdev); - if (err) - return err; - - sphw_aeq_register_hw_cb(hwdev, SPHW_MBX_FROM_FUNC, sphw_mbox_func_aeqe_handler); - sphw_aeq_register_hw_cb(hwdev, SPHW_MSG_FROM_MGMT_CPU, sphw_mgmt_msg_aeqe_handler); - - if (!SPHW_IS_VF(hwdev)) - sphw_register_pf_mbox_cb(hwdev, SPHW_MOD_COMM, hwdev->func_to_func, - pf_handle_vf_comm_mbox); - else - sphw_register_vf_mbox_cb(hwdev, SPHW_MOD_COMM, hwdev->func_to_func, - vf_handle_pf_comm_mbox); - - return 0; -} - -static void sphw_comm_func_to_func_free(struct sphw_hwdev *hwdev) -{ - sphw_aeq_unregister_hw_cb(hwdev, SPHW_MBX_FROM_FUNC); - - if (!SPHW_IS_VF(hwdev)) { - sphw_unregister_pf_mbox_cb(hwdev, SPHW_MOD_COMM); - } else { - sphw_unregister_vf_mbox_cb(hwdev, SPHW_MOD_COMM); - - sphw_aeq_unregister_hw_cb(hwdev, SPHW_MSG_FROM_MGMT_CPU); - } - - sphw_func_to_func_free(hwdev); -} - -static int sphw_comm_pf_to_mgmt_init(struct sphw_hwdev *hwdev) -{ - int err; - - /* VF do not support api chain */ - if (sphw_func_type(hwdev) == TYPE_VF || - !COMM_SUPPORT_API_CHAIN(hwdev)) - return 0; - - err = sphw_pf_to_mgmt_init(hwdev); - if (err) - return err; - - sphw_register_mgmt_msg_cb(hwdev, SPHW_MOD_COMM, hwdev->pf_to_mgmt, - pf_handle_mgmt_comm_event); - - return 0; -} - -static void sphw_comm_pf_to_mgmt_free(struct sphw_hwdev *hwdev) -{ - /* VF do not support api chain */ - if (sphw_func_type(hwdev) == TYPE_VF || - !COMM_SUPPORT_API_CHAIN(hwdev)) - return; - - sphw_unregister_mgmt_msg_cb(hwdev, SPHW_MOD_COMM); - - sphw_aeq_unregister_hw_cb(hwdev, SPHW_MSG_FROM_MGMT_CPU); - - sphw_pf_to_mgmt_free(hwdev); -} - -static int sphw_comm_cmdqs_init(struct sphw_hwdev *hwdev) -{ - int err; - - err = sphw_cmdqs_init(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init cmd queues\n"); - return err; - } - - sphw_ceq_register_cb(hwdev, SPHW_CMDQ, sphw_cmdq_ceq_handler); - - err = sphw_set_cmdq_depth(hwdev, SPHW_CMDQ_DEPTH); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to set cmdq depth\n"); - goto set_cmdq_depth_err; - } - - return 0; - -set_cmdq_depth_err: - sphw_cmdqs_free(hwdev); - - return err; -} - -static void sphw_comm_cmdqs_free(struct sphw_hwdev *hwdev) -{ - sphw_ceq_unregister_cb(hwdev, SPHW_CMDQ); - sphw_cmdqs_free(hwdev); -} - -static void sphw_sync_mgmt_func_state(struct sphw_hwdev *hwdev) -{ - sphw_set_pf_status(hwdev->hwif, SPHW_PF_STATUS_ACTIVE_FLAG); -} - -static void sphw_unsync_mgmt_func_state(struct sphw_hwdev *hwdev) -{ - sphw_set_pf_status(hwdev->hwif, SPHW_PF_STATUS_INIT); -} - -static int init_basic_attributes(struct sphw_hwdev *hwdev) -{ - u64 drv_feature[COMM_MAX_FEATURE_QWORD] = {SPHW_DRV_FEATURE_QW0}; - int err, i; - - err = sphw_get_board_info(hwdev, &hwdev->board_info, SPHW_CHANNEL_COMM); - if (err) - return err; - - err = sphw_get_comm_features(hwdev, hwdev->features, COMM_MAX_FEATURE_QWORD); - if (err) { - sdk_err(hwdev->dev_hdl, "Get comm features failed\n"); - return err; - } - - sdk_info(hwdev->dev_hdl, "Comm hw features: 0x%llx, drv features: 0x%llx\n", - hwdev->features[0], drv_feature[0]); - - for (i = 0; i < COMM_MAX_FEATURE_QWORD; i++) - hwdev->features[i] &= drv_feature[i]; - - err = sphw_get_global_attr(hwdev, &hwdev->glb_attr); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to get global attribute\n"); - return err; - } - - sdk_info(hwdev->dev_hdl, "global attribute: max_host: 0x%x, max_pf: 0x%x, vf_id_start: 0x%x, mgmt cpu node id: 0x%x\n", - hwdev->glb_attr.max_host_num, hwdev->glb_attr.max_pf_num, - hwdev->glb_attr.vf_id_start, - hwdev->glb_attr.mgmt_host_node_id); - - sphw_init_profile_adapter(hwdev); - - return 0; -} - -static int init_basic_mgmt_channel(struct sphw_hwdev *hwdev) -{ - int err; - - err = sphw_comm_aeqs_init(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init async event queues\n"); - return err; - } - - err = sphw_comm_func_to_func_init(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init mailbox\n"); - goto func_to_func_init_err; - } - - err = init_aeqs_msix_attr(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init aeqs msix attr\n"); - goto aeqs_msix_attr_init_err; - } - - return 0; - -aeqs_msix_attr_init_err: - sphw_comm_func_to_func_free(hwdev); - -func_to_func_init_err: - sphw_comm_aeqs_free(hwdev); - - return err; -} - -static void free_base_mgmt_channel(struct sphw_hwdev *hwdev) -{ - sphw_comm_func_to_func_free(hwdev); - sphw_comm_aeqs_free(hwdev); -} - -static int init_pf_mgmt_channel(struct sphw_hwdev *hwdev) -{ - int err; - - err = sphw_comm_pf_to_mgmt_init(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init pf to mgmt\n"); - return err; - } - - return 0; -} - -static void free_pf_mgmt_channel(struct sphw_hwdev *hwdev) -{ - sphw_comm_pf_to_mgmt_free(hwdev); -} - -static int init_mgmt_channel_post(struct sphw_hwdev *hwdev) -{ - int err; - - /* mbox host channel resources will be freed in - * sphw_func_to_func_free - */ - err = sphw_mbox_init_host_msg_channel(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init mbox host channel\n"); - return err; - } - - err = init_pf_mgmt_channel(hwdev); - if (err) - return err; - - return 0; -} - -static void free_mgmt_msg_channel_post(struct sphw_hwdev *hwdev) -{ - free_pf_mgmt_channel(hwdev); -} - -static int init_cmdqs_channel(struct sphw_hwdev *hwdev) -{ - int err; - - err = dma_attr_table_init(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init dma attr table\n"); - goto dma_attr_init_err; - } - - err = sphw_comm_ceqs_init(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init completion event queues\n"); - goto ceqs_init_err; - } - - err = init_ceqs_msix_attr(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init ceqs msix attr\n"); - goto init_ceq_msix_err; - } - - /* set default wq page_size */ - if (wq_page_order > SPHW_MAX_WQ_PAGE_SIZE_ORDER) { - sdk_info(hwdev->dev_hdl, "wq_page_order exceed limit[0, %d], reset to %d\n", - SPHW_MAX_WQ_PAGE_SIZE_ORDER, - SPHW_MAX_WQ_PAGE_SIZE_ORDER); - wq_page_order = SPHW_MAX_WQ_PAGE_SIZE_ORDER; - } - hwdev->wq_page_size = SPHW_HW_WQ_PAGE_SIZE * (1U << wq_page_order); - sdk_info(hwdev->dev_hdl, "WQ page size: 0x%x\n", hwdev->wq_page_size); - err = sphw_set_wq_page_size(hwdev, sphw_global_func_id(hwdev), hwdev->wq_page_size, - SPHW_CHANNEL_COMM); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to set wq page size\n"); - goto init_wq_pg_size_err; - } - - err = sphw_comm_cmdqs_init(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init cmd queues\n"); - goto cmdq_init_err; - } - - return 0; - -cmdq_init_err: - if (SPHW_FUNC_TYPE(hwdev) != TYPE_VF) - sphw_set_wq_page_size(hwdev, sphw_global_func_id(hwdev), SPHW_HW_WQ_PAGE_SIZE, - SPHW_CHANNEL_COMM); -init_wq_pg_size_err: -init_ceq_msix_err: - sphw_comm_ceqs_free(hwdev); - -ceqs_init_err: -dma_attr_init_err: - - return err; -} - -int sphw_init_comm_ch(struct sphw_hwdev *hwdev) -{ - int err; - - err = init_basic_mgmt_channel(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init mgmt channel\n"); - return err; - } - - err = sphw_func_reset(hwdev, sphw_global_func_id(hwdev), SPHW_COMM_RES, SPHW_CHANNEL_COMM); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to reset function\n"); - goto func_reset_err; - } - - err = init_basic_attributes(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init basic attributes\n"); - goto init_basic_attr_err; - } - - err = init_mgmt_channel_post(hwdev); - if (err) - goto init_mgmt_channel_post_err; - - err = init_cmdqs_channel(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init cmdq channel\n"); - goto init_cmdqs_channel_err; - } - - sphw_sync_mgmt_func_state(hwdev); - - if (SPHW_F_CHANNEL_LOCK_EN(hwdev)) { - sphw_mbox_enable_channel_lock(hwdev, true); - sphw_cmdq_enable_channel_lock(hwdev, true); - } - - return 0; - -init_cmdqs_channel_err: - free_mgmt_msg_channel_post(hwdev); -init_mgmt_channel_post_err: -init_basic_attr_err: -func_reset_err: - free_base_mgmt_channel(hwdev); - - return err; -} - -void sphw_uninit_comm_ch(struct sphw_hwdev *hwdev) -{ - sphw_unsync_mgmt_func_state(hwdev); - - sphw_comm_cmdqs_free(hwdev); - - if (SPHW_FUNC_TYPE(hwdev) != TYPE_VF) - sphw_set_wq_page_size(hwdev, sphw_global_func_id(hwdev), SPHW_HW_WQ_PAGE_SIZE, - SPHW_CHANNEL_COMM); - - sphw_comm_ceqs_free(hwdev); - - sphw_deinit_profile_adapter(hwdev); - - free_mgmt_msg_channel_post(hwdev); - - free_base_mgmt_channel(hwdev); -} - -int sphw_init_hwdev(struct sphw_init_para *para) -{ - struct sphw_hwdev *hwdev; - int err; - - hwdev = kzalloc(sizeof(*hwdev), GFP_KERNEL); - if (!hwdev) - return -ENOMEM; - - *para->hwdev = hwdev; - hwdev->adapter_hdl = para->adapter_hdl; - hwdev->pcidev_hdl = para->pcidev_hdl; - hwdev->dev_hdl = para->dev_hdl; - hwdev->chip_node = para->chip_node; - - hwdev->chip_fault_stats = vzalloc(SPHW_CHIP_FAULT_SIZE); - if (!hwdev->chip_fault_stats) - goto alloc_chip_fault_stats_err; - - err = sphw_init_hwif(hwdev, para->cfg_reg_base, para->intr_reg_base, - para->mgmt_reg_base, para->db_base_phy, - para->db_base, para->db_dwqe_len); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init hwif\n"); - goto init_hwif_err; - } - - sphw_set_chip_present(hwdev); - - if (disable_cfg_comm) - return 0; - - hwdev->workq = alloc_workqueue(SPHW_HWDEV_WQ_NAME, WQ_MEM_RECLAIM, - SPHW_WQ_MAX_REQ); - if (!hwdev->workq) { - sdk_err(hwdev->dev_hdl, "Failed to alloc hardware workq\n"); - goto alloc_workq_err; - } - - sphw_init_heartbeat_detect(hwdev); - - err = init_cfg_mgmt(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init config mgmt\n"); - goto init_cfg_mgmt_err; - } - - err = sphw_init_comm_ch(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init communication channel\n"); - goto init_comm_ch_err; - } - - err = init_capability(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init capability\n"); - goto init_cap_err; - } - - err = sphw_set_comm_features(hwdev, hwdev->features, COMM_MAX_FEATURE_QWORD); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to set comm features\n"); - goto set_feature_err; - } - - return 0; - -set_feature_err: - free_capability(hwdev); - -init_cap_err: - sphw_uninit_comm_ch(hwdev); - -init_comm_ch_err: - free_cfg_mgmt(hwdev); - -init_cfg_mgmt_err: - sphw_destroy_heartbeat_detect(hwdev); - destroy_workqueue(hwdev->workq); - -alloc_workq_err: - sphw_free_hwif(hwdev); - -init_hwif_err: - vfree(hwdev->chip_fault_stats); - -alloc_chip_fault_stats_err: - kfree(hwdev); - *para->hwdev = NULL; - - return -EFAULT; -} - -void sphw_free_hwdev(void *hwdev) -{ - struct sphw_hwdev *dev = hwdev; - - sphw_func_rx_tx_flush(hwdev, SPHW_CHANNEL_COMM); - - free_capability(dev); - - sphw_uninit_comm_ch(dev); - - free_cfg_mgmt(dev); - sphw_destroy_heartbeat_detect(hwdev); - destroy_workqueue(dev->workq); - sphw_free_hwif(dev); - vfree(dev->chip_fault_stats); - - kfree(dev); -} - -void *sphw_get_pcidev_hdl(void *hwdev) -{ - struct sphw_hwdev *dev = (struct sphw_hwdev *)hwdev; - - if (!hwdev) - return NULL; - - return dev->pcidev_hdl; -} - -int sphw_register_service_adapter(void *hwdev, void *service_adapter, enum sphw_service_type type) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev || !service_adapter || type >= SERVICE_T_MAX) - return -EINVAL; - - if (dev->service_adapter[type]) - return -EINVAL; - - dev->service_adapter[type] = service_adapter; - - return 0; -} - -void sphw_unregister_service_adapter(void *hwdev, enum sphw_service_type type) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev || type >= SERVICE_T_MAX) - return; - - dev->service_adapter[type] = NULL; -} - -void *sphw_get_service_adapter(void *hwdev, enum sphw_service_type type) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev || type >= SERVICE_T_MAX) - return NULL; - - return dev->service_adapter[type]; -} - -int sphw_dbg_get_hw_stats(const void *hwdev, u8 *hw_stats, u16 *out_size) -{ - if (*out_size != sizeof(struct sphw_hw_stats)) { - pr_err("Unexpect out buf size from user :%u, expect: %lu\n", - *out_size, sizeof(struct sphw_hw_stats)); - return -EFAULT; - } - - memcpy(hw_stats, &((struct sphw_hwdev *)hwdev)->hw_stats, - sizeof(struct sphw_hw_stats)); - return 0; -} - -u16 sphw_dbg_clear_hw_stats(void *hwdev) -{ - memset((void *)&((struct sphw_hwdev *)hwdev)->hw_stats, 0, - sizeof(struct sphw_hw_stats)); - memset((void *)((struct sphw_hwdev *)hwdev)->chip_fault_stats, 0, - SPHW_CHIP_FAULT_SIZE); - return sizeof(struct sphw_hw_stats); -} - -void sphw_get_chip_fault_stats(const void *hwdev, u8 *chip_fault_stats, u32 offset) -{ - u32 copy_len = offset + MAX_DRV_BUF_SIZE - SPHW_CHIP_FAULT_SIZE; - - if (offset + MAX_DRV_BUF_SIZE <= SPHW_CHIP_FAULT_SIZE) - memcpy(chip_fault_stats, - ((struct sphw_hwdev *)hwdev)->chip_fault_stats - + offset, MAX_DRV_BUF_SIZE); - else - memcpy(chip_fault_stats, - ((struct sphw_hwdev *)hwdev)->chip_fault_stats - + offset, copy_len); -} - -void sphw_event_register(void *dev, void *pri_handle, sphw_event_handler callback) -{ - struct sphw_hwdev *hwdev = dev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for register event\n"); - return; - } - - hwdev->event_callback = callback; - hwdev->event_pri_handle = pri_handle; -} - -void sphw_event_unregister(void *dev) -{ - struct sphw_hwdev *hwdev = dev; - - if (!dev) { - pr_err("Hwdev pointer is NULL for register event\n"); - return; - } - - hwdev->event_callback = NULL; - hwdev->event_pri_handle = NULL; -} - -void sphw_event_callback(void *hwdev, struct sphw_event_info *event) -{ - struct sphw_hwdev *dev = hwdev; - - if (!hwdev) { - pr_err("Hwdev pointer is NULL for event callback\n"); - return; - } - - if (!dev->event_callback) { - sdk_info(dev->dev_hdl, "Event callback function not register\n"); - return; - } - - dev->event_callback(dev->event_pri_handle, event); -} - -void sphw_set_pcie_order_cfg(void *handle) -{ -} - -void sphw_disable_mgmt_msg_report(void *hwdev) -{ - struct sphw_hwdev *hw_dev = (struct sphw_hwdev *)hwdev; - - sphw_set_pf_status(hw_dev->hwif, SPHW_PF_STATUS_INIT); -} - -void sphw_record_pcie_error(void *hwdev) -{ - struct sphw_hwdev *dev = (struct sphw_hwdev *)hwdev; - - if (!hwdev) - return; - - atomic_inc(&dev->hw_stats.fault_event_stats.pcie_fault_stats); -} - -int sphw_get_card_present_state(void *hwdev, bool *card_present_state) -{ - struct sphw_hwdev *dev = hwdev; - u32 addr, attr1; - - if (!hwdev || !card_present_state) - return -EINVAL; - - addr = SPHW_CSR_FUNC_ATTR1_ADDR; - attr1 = sphw_hwif_read_reg(dev->hwif, addr); - if (attr1 == SPHW_PCIE_LINK_DOWN) { - sdk_warn(dev->dev_hdl, "Card is not present\n"); - *card_present_state = (bool)0; - } else { - *card_present_state = (bool)1; - } - - return 0; -} - -void sphw_link_event_stats(void *dev, u8 link) -{ - struct sphw_hwdev *hwdev = dev; - - if (link) - atomic_inc(&hwdev->hw_stats.link_event_stats.link_up_stats); - else - atomic_inc(&hwdev->hw_stats.link_event_stats.link_down_stats); -} - -u8 sphw_max_pf_num(void *hwdev) -{ - if (!hwdev) - return 0; - - return SPHW_MAX_PF_NUM((struct sphw_hwdev *)hwdev); -} - -void sphw_fault_event_report(void *hwdev, u16 src, u16 level) -{ - if (!hwdev) - return; - - sdk_info(((struct sphw_hwdev *)hwdev)->dev_hdl, "Fault event report, src: %u, level: %u\n", - src, level); - - sphw_fault_post_process(hwdev, src, level); -} - -void sphw_heartbeat_lost_handler(struct work_struct *work) -{ - struct sphw_event_info event_info = { 0 }; - struct sphw_hwdev *hwdev = container_of(work, struct sphw_hwdev, - heartbeat_lost_work); - u16 src, level; - - atomic_inc(&hwdev->hw_stats.heart_lost_stats); - - if (hwdev->event_callback) { - event_info.type = - hwdev->pcie_link_down ? SPHW_EVENT_PCIE_LINK_DOWN : - SPHW_EVENT_HEART_LOST; - hwdev->event_callback(hwdev->event_pri_handle, &event_info); - } - - if (hwdev->pcie_link_down) { - src = SPHW_FAULT_SRC_PCIE_LINK_DOWN; - level = FAULT_LEVEL_HOST; - sdk_err(hwdev->dev_hdl, "Detect pcie is link down\n"); - } else { - src = SPHW_FAULT_SRC_HOST_HEARTBEAT_LOST; - level = FAULT_LEVEL_FATAL; - sdk_err(hwdev->dev_hdl, "Heart lost report received, func_id: %d\n", - sphw_global_func_id(hwdev)); - } - - sphw_fault_post_process(hwdev, src, level); -} - -#define DETECT_PCIE_LINK_DOWN_RETRY 2 -#define SPHW_HEARTBEAT_START_EXPIRE 5000 -#define SPHW_HEARTBEAT_PERIOD 1000 - -static bool sphw_is_hw_abnormal(struct sphw_hwdev *hwdev) -{ - u32 status; - - if (!sphw_get_chip_present_flag(hwdev)) - return false; - - status = sphw_get_heartbeat_status(hwdev); - if (status == SPHW_PCIE_LINK_DOWN) { - sdk_warn(hwdev->dev_hdl, "Detect BAR register read failed\n"); - hwdev->rd_bar_err_cnt++; - if (hwdev->rd_bar_err_cnt >= DETECT_PCIE_LINK_DOWN_RETRY) { - sphw_set_chip_absent(hwdev); - sphw_force_complete_all(hwdev); - hwdev->pcie_link_down = true; - return true; - } - - return false; - } - - if (status) { - hwdev->heartbeat_lost = true; - return true; - } - - hwdev->rd_bar_err_cnt = 0; - - return false; -} - -static void sphw_heartbeat_timer_handler(struct timer_list *t) -{ - struct sphw_hwdev *hwdev = from_timer(hwdev, t, heartbeat_timer); - - if (sphw_is_hw_abnormal(hwdev)) - queue_work(hwdev->workq, &hwdev->heartbeat_lost_work); - else - mod_timer(&hwdev->heartbeat_timer, - jiffies + msecs_to_jiffies(SPHW_HEARTBEAT_PERIOD)); -} - -static void sphw_init_heartbeat_detect(struct sphw_hwdev *hwdev) -{ - timer_setup(&hwdev->heartbeat_timer, sphw_heartbeat_timer_handler, 0); - - hwdev->heartbeat_timer.expires = - jiffies + msecs_to_jiffies(SPHW_HEARTBEAT_START_EXPIRE); - - add_timer(&hwdev->heartbeat_timer); - - INIT_WORK(&hwdev->heartbeat_lost_work, sphw_heartbeat_lost_handler); -} - -static void sphw_destroy_heartbeat_detect(struct sphw_hwdev *hwdev) -{ - del_timer_sync(&hwdev->heartbeat_timer); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwdev.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwdev.h deleted file mode 100644 index 10da31bda3d2..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwdev.h +++ /dev/null @@ -1,93 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_HWDEV_H -#define SPHW_HWDEV_H - -#include "sphw_mt.h" -#include "sphw_crm.h" -#include "sphw_hw.h" - -struct cfg_mgmt_info; - -struct sphw_hwif; -struct sphw_aeqs; -struct sphw_ceqs; -struct sphw_mbox; -struct sphw_msg_pf_to_mgmt; - -struct sphw_page_addr { - void *virt_addr; - u64 phys_addr; -}; - -struct mqm_addr_trans_tbl_info { - u32 chunk_num; - u32 search_gpa_num; - u32 page_size; - u32 page_num; - struct sphw_page_addr *brm_srch_page_addr; -}; - -struct sphw_hwdev { - void *adapter_hdl; /* pointer to spnic_pcidev or NDIS_Adapter */ - void *pcidev_hdl; /* pointer to pcidev or Handler */ - void *dev_hdl; /* pointer to pcidev->dev or Handler, for - * sdk_err() or dma_alloc() - */ - - void *service_adapter[SERVICE_T_MAX]; - void *chip_node; - void *ppf_hwdev; - - u32 wq_page_size; - int chip_present_flag; - - struct sphw_hwif *hwif; /* include void __iomem *bar */ - struct comm_global_attr glb_attr; - u64 features[COMM_MAX_FEATURE_QWORD]; - - struct cfg_mgmt_info *cfg_mgmt; - - struct sphw_cmdqs *cmdqs; - struct sphw_aeqs *aeqs; - struct sphw_ceqs *ceqs; - struct sphw_mbox *func_to_func; - struct sphw_msg_pf_to_mgmt *pf_to_mgmt; - - void *cqm_hdl; - struct mqm_addr_trans_tbl_info mqm_att; - struct sphw_page_addr page_pa0; - struct sphw_page_addr page_pa1; - u32 statufull_ref_cnt; - - struct sphw_hw_stats hw_stats; - u8 *chip_fault_stats; - - sphw_event_handler event_callback; - void *event_pri_handle; - - struct sphw_board_info board_info; - - int prof_adap_type; - struct sphw_prof_attr *prof_attr; - - struct workqueue_struct *workq; - - u32 rd_bar_err_cnt; - bool pcie_link_down; - bool heartbeat_lost; - struct timer_list heartbeat_timer; - struct work_struct heartbeat_lost_work; -}; - -#define SPHW_MAX_HOST_NUM(hwdev) ((hwdev)->glb_attr.max_host_num) -#define SPHW_MAX_PF_NUM(hwdev) ((hwdev)->glb_attr.max_pf_num) -#define SPHW_MGMT_CPU_NODE_ID(hwdev) ((hwdev)->glb_attr.mgmt_host_node_id) - -#define COMM_FEATURE_QW0(hwdev, feature) ((hwdev)->features[0] & COMM_F_##feature) -#define COMM_SUPPORT_API_CHAIN(hwdev) COMM_FEATURE_QW0(hwdev, API_CHAIN) - -#define SPHW_DRV_FEATURE_QW0 COMM_F_API_CHAIN - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwif.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwif.c deleted file mode 100644 index fbb1128957f0..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwif.c +++ /dev/null @@ -1,886 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/module.h> - -#include "sphw_csr.h" -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_common.h" -#include "sphw_hwdev.h" -#include "sphw_hwif.h" - -#define WAIT_HWIF_READY_TIMEOUT 10000 -#define SPHW_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT 60000 - -#define DB_IDX(db, db_base) \ - ((u32)(((ulong)(db) - (ulong)(db_base)) / \ - SPHW_DB_PAGE_SIZE)) - -#define SPHW_AF0_FUNC_GLOBAL_IDX_SHIFT 0 -#define SPHW_AF0_P2P_IDX_SHIFT 12 -#define SPHW_AF0_PCI_INTF_IDX_SHIFT 17 -#define SPHW_AF0_VF_IN_PF_SHIFT 20 -#define SPHW_AF0_FUNC_TYPE_SHIFT 28 - -#define SPHW_AF0_FUNC_GLOBAL_IDX_MASK 0xFFF -#define SPHW_AF0_P2P_IDX_MASK 0x1F -#define SPHW_AF0_PCI_INTF_IDX_MASK 0x7 -#define SPHW_AF0_VF_IN_PF_MASK 0xFF -#define SPHW_AF0_FUNC_TYPE_MASK 0x1 - -#define SPHW_AF0_GET(val, member) \ - (((val) >> SPHW_AF0_##member##_SHIFT) & SPHW_AF0_##member##_MASK) - -#define SPHW_AF1_PPF_IDX_SHIFT 0 -#define SPHW_AF1_AEQS_PER_FUNC_SHIFT 8 -#define SPHW_AF1_MGMT_INIT_STATUS_SHIFT 30 -#define SPHW_AF1_PF_INIT_STATUS_SHIFT 31 - -#define SPHW_AF1_PPF_IDX_MASK 0x3F -#define SPHW_AF1_AEQS_PER_FUNC_MASK 0x3 -#define SPHW_AF1_MGMT_INIT_STATUS_MASK 0x1 -#define SPHW_AF1_PF_INIT_STATUS_MASK 0x1 - -#define SPHW_AF1_GET(val, member) \ - (((val) >> SPHW_AF1_##member##_SHIFT) & SPHW_AF1_##member##_MASK) - -#define SPHW_AF2_CEQS_PER_FUNC_SHIFT 0 -#define SPHW_AF2_DMA_ATTR_PER_FUNC_SHIFT 9 -#define SPHW_AF2_IRQS_PER_FUNC_SHIFT 16 - -#define SPHW_AF2_CEQS_PER_FUNC_MASK 0x1FF -#define SPHW_AF2_DMA_ATTR_PER_FUNC_MASK 0x7 -#define SPHW_AF2_IRQS_PER_FUNC_MASK 0x7FF - -#define SPHW_AF2_GET(val, member) \ - (((val) >> SPHW_AF2_##member##_SHIFT) & SPHW_AF2_##member##_MASK) - -#define SPHW_AF3_GLOBAL_VF_ID_OF_NXT_PF_SHIFT 0 -#define SPHW_AF3_GLOBAL_VF_ID_OF_PF_SHIFT 16 - -#define SPHW_AF3_GLOBAL_VF_ID_OF_NXT_PF_MASK 0xFFF -#define SPHW_AF3_GLOBAL_VF_ID_OF_PF_MASK 0xFFF - -#define SPHW_AF3_GET(val, member) \ - (((val) >> SPHW_AF3_##member##_SHIFT) & SPHW_AF3_##member##_MASK) - -#define SPHW_AF4_DOORBELL_CTRL_SHIFT 0 -#define SPHW_AF4_DOORBELL_CTRL_MASK 0x1 - -#define SPHW_AF4_GET(val, member) \ - (((val) >> SPHW_AF4_##member##_SHIFT) & SPHW_AF4_##member##_MASK) - -#define SPHW_AF4_SET(val, member) \ - (((val) & SPHW_AF4_##member##_MASK) << SPHW_AF4_##member##_SHIFT) - -#define SPHW_AF4_CLEAR(val, member) \ - ((val) & (~(SPHW_AF4_##member##_MASK << SPHW_AF4_##member##_SHIFT))) - -#define SPHW_AF5_OUTBOUND_CTRL_SHIFT 0 -#define SPHW_AF5_OUTBOUND_CTRL_MASK 0x1 - -#define SPHW_AF5_GET(val, member) \ - (((val) >> SPHW_AF5_##member##_SHIFT) & SPHW_AF5_##member##_MASK) - -#define SPHW_AF5_SET(val, member) \ - (((val) & SPHW_AF5_##member##_MASK) << SPHW_AF5_##member##_SHIFT) - -#define SPHW_AF5_CLEAR(val, member) \ - ((val) & (~(SPHW_AF5_##member##_MASK << SPHW_AF5_##member##_SHIFT))) - -#define SPHW_AF6_PF_STATUS_SHIFT 0 -#define SPHW_AF6_PF_STATUS_MASK 0xFFFF - -#define SPHW_AF6_SET(val, member) \ - ((((u32)(val)) & SPHW_AF6_##member##_MASK) << \ - SPHW_AF6_##member##_SHIFT) - -#define SPHW_AF6_GET(val, member) \ - (((val) >> SPHW_AF6_##member##_SHIFT) & SPHW_AF6_##member##_MASK) - -#define SPHW_AF6_CLEAR(val, member) \ - ((val) & (~(SPHW_AF6_##member##_MASK << \ - SPHW_AF6_##member##_SHIFT))) - -#define sphw_PPF_ELECT_PORT_IDX_SHIFT 0 - -#define sphw_PPF_ELECT_PORT_IDX_MASK 0x3F - -#define sphw_PPF_ELECT_PORT_GET(val, member) \ - (((val) >> sphw_PPF_ELECT_PORT_##member##_SHIFT) & \ - sphw_PPF_ELECT_PORT_##member##_MASK) - -#define SPHW_PPF_ELECTION_IDX_SHIFT 0 - -#define SPHW_PPF_ELECTION_IDX_MASK 0x3F - -#define SPHW_PPF_ELECTION_SET(val, member) \ - (((val) & SPHW_PPF_ELECTION_##member##_MASK) << \ - SPHW_PPF_ELECTION_##member##_SHIFT) - -#define SPHW_PPF_ELECTION_GET(val, member) \ - (((val) >> SPHW_PPF_ELECTION_##member##_SHIFT) & \ - SPHW_PPF_ELECTION_##member##_MASK) - -#define SPHW_PPF_ELECTION_CLEAR(val, member) \ - ((val) & (~(SPHW_PPF_ELECTION_##member##_MASK << \ - SPHW_PPF_ELECTION_##member##_SHIFT))) - -#define SPHW_MPF_ELECTION_IDX_SHIFT 0 - -#define SPHW_MPF_ELECTION_IDX_MASK 0x1F - -#define SPHW_MPF_ELECTION_SET(val, member) \ - (((val) & SPHW_MPF_ELECTION_##member##_MASK) << \ - SPHW_MPF_ELECTION_##member##_SHIFT) - -#define SPHW_MPF_ELECTION_GET(val, member) \ - (((val) >> SPHW_MPF_ELECTION_##member##_SHIFT) & \ - SPHW_MPF_ELECTION_##member##_MASK) - -#define SPHW_MPF_ELECTION_CLEAR(val, member) \ - ((val) & (~(SPHW_MPF_ELECTION_##member##_MASK << \ - SPHW_MPF_ELECTION_##member##_SHIFT))) - -#define SPHW_GET_REG_FLAG(reg) ((reg) & (~(SPHW_REGS_FLAG_MAKS))) - -#define SPHW_GET_REG_ADDR(reg) ((reg) & (SPHW_REGS_FLAG_MAKS)) - -u32 sphw_hwif_read_reg(struct sphw_hwif *hwif, u32 reg) -{ - if (SPHW_GET_REG_FLAG(reg) == SPHW_MGMT_REGS_FLAG) - return be32_to_cpu(readl(hwif->mgmt_regs_base + - SPHW_GET_REG_ADDR(reg))); - else - return be32_to_cpu(readl(hwif->cfg_regs_base + - SPHW_GET_REG_ADDR(reg))); -} - -void sphw_hwif_write_reg(struct sphw_hwif *hwif, u32 reg, u32 val) -{ - if (SPHW_GET_REG_FLAG(reg) == SPHW_MGMT_REGS_FLAG) - writel(cpu_to_be32(val), - hwif->mgmt_regs_base + SPHW_GET_REG_ADDR(reg)); - else - writel(cpu_to_be32(val), - hwif->cfg_regs_base + SPHW_GET_REG_ADDR(reg)); -} - -/** - * sphw_get_heartbeat_status - get heart beat status - * @hwdev: the pointer to hw device - * Return: 0 - normal, 1 - heart lost, 0xFFFFFFFF - Pcie link down - **/ -u32 sphw_get_heartbeat_status(struct sphw_hwdev *hwdev) -{ - u32 attr1; - - attr1 = sphw_hwif_read_reg(hwdev->hwif, SPHW_CSR_FUNC_ATTR1_ADDR); - if (attr1 == SPHW_PCIE_LINK_DOWN) - return attr1; - - return !SPHW_AF1_GET(attr1, MGMT_INIT_STATUS); -} - -/** - * hwif_ready - test if the HW initialization passed - * @hwdev: the pointer to hw device - * Return: 0 - success, negative - failure - **/ -static int hwif_ready(struct sphw_hwdev *hwdev) -{ - if (sphw_get_heartbeat_status(hwdev)) - return -EBUSY; - - return 0; -} - -static enum sphw_wait_return check_hwif_ready_handler(void *priv_data) -{ - if (!hwif_ready(priv_data)) - return WAIT_PROCESS_CPL; - - return WAIT_PROCESS_WAITING; -} - -static int wait_hwif_ready(struct sphw_hwdev *hwdev) -{ - if (!sphw_wait_for_timeout(hwdev, check_hwif_ready_handler, - WAIT_HWIF_READY_TIMEOUT, USEC_PER_MSEC)) - return 0; - - sdk_err(hwdev->dev_hdl, "Wait for hwif timeout\n"); - return -EBUSY; -} - -/** - * set_hwif_attr - set the attributes as members in hwif - * @hwif: the hardware interface of a pci function device - * @attr0: the first attribute that was read from the hw - * @attr1: the second attribute that was read from the hw - * @attr2: the third attribute that was read from the hw - * @attr3: the fourth attribute that was read from the hw - **/ -static void set_hwif_attr(struct sphw_hwif *hwif, u32 attr0, u32 attr1, - u32 attr2, u32 attr3) -{ - hwif->attr.func_global_idx = SPHW_AF0_GET(attr0, FUNC_GLOBAL_IDX); - hwif->attr.port_to_port_idx = SPHW_AF0_GET(attr0, P2P_IDX); - hwif->attr.pci_intf_idx = SPHW_AF0_GET(attr0, PCI_INTF_IDX); - hwif->attr.vf_in_pf = SPHW_AF0_GET(attr0, VF_IN_PF); - hwif->attr.func_type = SPHW_AF0_GET(attr0, FUNC_TYPE); - - hwif->attr.ppf_idx = SPHW_AF1_GET(attr1, PPF_IDX); - hwif->attr.num_aeqs = BIT(SPHW_AF1_GET(attr1, AEQS_PER_FUNC)); - hwif->attr.num_ceqs = (u8)SPHW_AF2_GET(attr2, CEQS_PER_FUNC); - hwif->attr.num_irqs = SPHW_AF2_GET(attr2, IRQS_PER_FUNC); - hwif->attr.num_dma_attr = BIT(SPHW_AF2_GET(attr2, DMA_ATTR_PER_FUNC)); - - hwif->attr.global_vf_id_of_pf = SPHW_AF3_GET(attr3, GLOBAL_VF_ID_OF_PF); - - pr_info("func_global_idx: 0x%x, port_to_port_idx: 0x%x, pci_intf_idx: 0x%x, vf_in_pf: 0x%x, func_type: %d\n", - hwif->attr.func_global_idx, hwif->attr.port_to_port_idx, - hwif->attr.pci_intf_idx, hwif->attr.vf_in_pf, - hwif->attr.func_type); - - pr_info("ppf_idx: 0x%x, num_aeqs: 0x%x, num_ceqs: 0x%x, num_irqs: 0x%x, num_dma_attr: 0x%x, global_vf_id_of_pf: %u\n", - hwif->attr.ppf_idx, hwif->attr.num_aeqs, - hwif->attr.num_ceqs, hwif->attr.num_irqs, - hwif->attr.num_dma_attr, hwif->attr.global_vf_id_of_pf); -} - -/** - * get_hwif_attr - read and set the attributes as members in hwif - * @hwif: the hardware interface of a pci function device - **/ -static void get_hwif_attr(struct sphw_hwif *hwif) -{ - u32 addr, attr0, attr1, attr2, attr3; - - addr = SPHW_CSR_FUNC_ATTR0_ADDR; - attr0 = sphw_hwif_read_reg(hwif, addr); - - addr = SPHW_CSR_FUNC_ATTR1_ADDR; - attr1 = sphw_hwif_read_reg(hwif, addr); - - addr = SPHW_CSR_FUNC_ATTR2_ADDR; - attr2 = sphw_hwif_read_reg(hwif, addr); - - addr = SPHW_CSR_FUNC_ATTR3_ADDR; - attr3 = sphw_hwif_read_reg(hwif, addr); - - pr_info("attr0: 0x%08x, attr1: 0x%08x, attr2: 0x%08x, attr3: 0x%08x\n", - attr0, attr1, attr2, attr3); - set_hwif_attr(hwif, attr0, attr1, attr2, attr3); -} - -void sphw_set_pf_status(struct sphw_hwif *hwif, enum sphw_pf_status status) -{ - u32 attr6 = SPHW_AF6_SET(status, PF_STATUS); - u32 addr = SPHW_CSR_FUNC_ATTR6_ADDR; - - if (hwif->attr.func_type == TYPE_VF) - return; - - sphw_hwif_write_reg(hwif, addr, attr6); -} - -enum sphw_pf_status sphw_get_pf_status(struct sphw_hwif *hwif) -{ - u32 attr6 = sphw_hwif_read_reg(hwif, SPHW_CSR_FUNC_ATTR6_ADDR); - - return SPHW_AF6_GET(attr6, PF_STATUS); -} - -enum sphw_doorbell_ctrl sphw_get_doorbell_ctrl_status(struct sphw_hwif *hwif) -{ - u32 attr4 = sphw_hwif_read_reg(hwif, SPHW_CSR_FUNC_ATTR4_ADDR); - - return SPHW_AF4_GET(attr4, DOORBELL_CTRL); -} - -enum sphw_outbound_ctrl sphw_get_outbound_ctrl_status(struct sphw_hwif *hwif) -{ - u32 attr5 = sphw_hwif_read_reg(hwif, SPHW_CSR_FUNC_ATTR5_ADDR); - - return SPHW_AF5_GET(attr5, OUTBOUND_CTRL); -} - -void sphw_enable_doorbell(struct sphw_hwif *hwif) -{ - u32 addr, attr4; - - addr = SPHW_CSR_FUNC_ATTR4_ADDR; - attr4 = sphw_hwif_read_reg(hwif, addr); - - attr4 = SPHW_AF4_CLEAR(attr4, DOORBELL_CTRL); - attr4 |= SPHW_AF4_SET(ENABLE_DOORBELL, DOORBELL_CTRL); - - sphw_hwif_write_reg(hwif, addr, attr4); -} - -void sphw_disable_doorbell(struct sphw_hwif *hwif) -{ - u32 addr, attr4; - - addr = SPHW_CSR_FUNC_ATTR4_ADDR; - attr4 = sphw_hwif_read_reg(hwif, addr); - - attr4 = SPHW_AF4_CLEAR(attr4, DOORBELL_CTRL); - attr4 |= SPHW_AF4_SET(DISABLE_DOORBELL, DOORBELL_CTRL); - - sphw_hwif_write_reg(hwif, addr, attr4); -} - -/** - * set_ppf - try to set hwif as ppf and set the type of hwif in this case - * @hwif: the hardware interface of a pci function device - **/ -static void set_ppf(struct sphw_hwif *hwif) -{ - struct sphw_func_attr *attr = &hwif->attr; - u32 addr, val, ppf_election; - - /* Read Modify Write */ - addr = SPHW_CSR_PPF_ELECTION_ADDR; - - val = sphw_hwif_read_reg(hwif, addr); - val = SPHW_PPF_ELECTION_CLEAR(val, IDX); - - ppf_election = SPHW_PPF_ELECTION_SET(attr->func_global_idx, IDX); - val |= ppf_election; - - sphw_hwif_write_reg(hwif, addr, val); - - /* Check PPF */ - val = sphw_hwif_read_reg(hwif, addr); - - attr->ppf_idx = SPHW_PPF_ELECTION_GET(val, IDX); - if (attr->ppf_idx == attr->func_global_idx) - attr->func_type = TYPE_PPF; -} - -/** - * get_mpf - get the mpf index into the hwif - * @hwif: the hardware interface of a pci function device - **/ -static void get_mpf(struct sphw_hwif *hwif) -{ - struct sphw_func_attr *attr = &hwif->attr; - u32 mpf_election, addr; - - addr = SPHW_CSR_GLOBAL_MPF_ELECTION_ADDR; - - mpf_election = sphw_hwif_read_reg(hwif, addr); - attr->mpf_idx = SPHW_MPF_ELECTION_GET(mpf_election, IDX); -} - -/** - * set_mpf - try to set hwif as mpf and set the mpf idx in hwif - * @hwif: the hardware interface of a pci function device - **/ -static void set_mpf(struct sphw_hwif *hwif) -{ - struct sphw_func_attr *attr = &hwif->attr; - u32 addr, val, mpf_election; - - /* Read Modify Write */ - addr = SPHW_CSR_GLOBAL_MPF_ELECTION_ADDR; - - val = sphw_hwif_read_reg(hwif, addr); - - val = SPHW_MPF_ELECTION_CLEAR(val, IDX); - mpf_election = SPHW_MPF_ELECTION_SET(attr->func_global_idx, IDX); - - val |= mpf_election; - sphw_hwif_write_reg(hwif, addr, val); -} - -static int init_db_area_idx(struct sphw_free_db_area *free_db_area, u64 db_dwqe_len) -{ - u32 db_max_areas; - - db_max_areas = (db_dwqe_len > SPHW_DB_DWQE_SIZE) ? SPHW_DB_MAX_AREAS : - (u32)(db_dwqe_len / SPHW_DB_PAGE_SIZE); - free_db_area->db_bitmap_array = bitmap_zalloc(db_max_areas, GFP_KERNEL); - if (!free_db_area->db_bitmap_array) { - pr_err("Failed to allocate db area.\n"); - return -ENOMEM; - } - free_db_area->db_max_areas = db_max_areas; - spin_lock_init(&free_db_area->idx_lock); - - return 0; -} - -static void free_db_area(struct sphw_free_db_area *free_db_area) -{ - kfree(free_db_area->db_bitmap_array); -} - -static int get_db_idx(struct sphw_hwif *hwif, u32 *idx) -{ - struct sphw_free_db_area *free_db_area = &hwif->free_db_area; - u32 pg_idx; - - spin_lock(&free_db_area->idx_lock); - pg_idx = (u32)find_first_zero_bit(free_db_area->db_bitmap_array, - free_db_area->db_max_areas); - if (pg_idx == free_db_area->db_max_areas) { - spin_unlock(&free_db_area->idx_lock); - return -ENOMEM; - } - set_bit(pg_idx, free_db_area->db_bitmap_array); - spin_unlock(&free_db_area->idx_lock); - - *idx = pg_idx; - - return 0; -} - -static void free_db_idx(struct sphw_hwif *hwif, u32 idx) -{ - struct sphw_free_db_area *free_db_area = &hwif->free_db_area; - - if (idx >= free_db_area->db_max_areas) - return; - - spin_lock(&free_db_area->idx_lock); - clear_bit((int)idx, free_db_area->db_bitmap_array); - - spin_unlock(&free_db_area->idx_lock); -} - -void sphw_free_db_addr(void *hwdev, const void __iomem *db_base, void __iomem *dwqe_base) -{ - struct sphw_hwif *hwif = NULL; - u32 idx; - - if (!hwdev || !db_base) - return; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - idx = DB_IDX(db_base, hwif->db_base); - - free_db_idx(hwif, idx); -} - -int sphw_alloc_db_addr(void *hwdev, void __iomem **db_base, void __iomem **dwqe_base) -{ - struct sphw_hwif *hwif = NULL; - u32 idx = 0; - int err; - - if (!hwdev || !db_base) - return -EINVAL; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - err = get_db_idx(hwif, &idx); - if (err) - return -EFAULT; - - *db_base = hwif->db_base + idx * SPHW_DB_PAGE_SIZE; - - if (!dwqe_base) - return 0; - - *dwqe_base = (u8 *)*db_base + SPHW_DWQE_OFFSET; - - return 0; -} - -void sphw_free_db_phy_addr(void *hwdev, u64 db_base, u64 dwqe_base) -{ - struct sphw_hwif *hwif = NULL; - u32 idx; - - if (!hwdev) - return; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - idx = DB_IDX(db_base, hwif->db_base_phy); - - free_db_idx(hwif, idx); -} - -int sphw_alloc_db_phy_addr(void *hwdev, u64 *db_base, u64 *dwqe_base) -{ - struct sphw_hwif *hwif = NULL; - u32 idx; - int err; - - if (!hwdev || !db_base || !dwqe_base) - return -EINVAL; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - err = get_db_idx(hwif, &idx); - if (err) - return -EFAULT; - - *db_base = hwif->db_base_phy + idx * SPHW_DB_PAGE_SIZE; - *dwqe_base = *db_base + SPHW_DWQE_OFFSET; - - return 0; -} - -void sphw_set_msix_auto_mask_state(void *hwdev, u16 msix_idx, enum sphw_msix_auto_mask flag) -{ - struct sphw_hwif *hwif = NULL; - u32 mask_bits; - u32 addr; - - if (!hwdev) - return; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - if (flag) - mask_bits = SPHW_MSI_CLR_INDIR_SET(1, AUTO_MSK_SET); - else - mask_bits = SPHW_MSI_CLR_INDIR_SET(1, AUTO_MSK_CLR); - - mask_bits = mask_bits | SPHW_MSI_CLR_INDIR_SET(msix_idx, SIMPLE_INDIR_IDX); - - addr = SPHW_CSR_FUNC_MSI_CLR_WR_ADDR; - sphw_hwif_write_reg(hwif, addr, mask_bits); -} - -void sphw_set_msix_state(void *hwdev, u16 msix_idx, enum sphw_msix_state flag) -{ - struct sphw_hwif *hwif = NULL; - u32 mask_bits; - u32 addr; - u8 int_msk = 1; - - if (!hwdev) - return; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - if (flag) - mask_bits = SPHW_MSI_CLR_INDIR_SET(int_msk, INT_MSK_SET); - else - mask_bits = SPHW_MSI_CLR_INDIR_SET(int_msk, INT_MSK_CLR); - mask_bits = mask_bits | SPHW_MSI_CLR_INDIR_SET(msix_idx, SIMPLE_INDIR_IDX); - - addr = SPHW_CSR_FUNC_MSI_CLR_WR_ADDR; - sphw_hwif_write_reg(hwif, addr, mask_bits); -} - -static void disable_all_msix(struct sphw_hwdev *hwdev) -{ - u16 num_irqs = hwdev->hwif->attr.num_irqs; - u16 i; - - for (i = 0; i < num_irqs; i++) - sphw_set_msix_state(hwdev, i, SPHW_MSIX_DISABLE); -} - -static enum sphw_wait_return check_db_flush_enable_handler(void *priv_data) -{ - struct sphw_hwif *hwif = priv_data; - enum sphw_doorbell_ctrl db_ctrl; - - db_ctrl = sphw_get_doorbell_ctrl_status(hwif); - if (db_ctrl == ENABLE_DOORBELL) - return WAIT_PROCESS_CPL; - - return WAIT_PROCESS_WAITING; -} - -static enum sphw_wait_return check_db_flush_disable_handler(void *priv_data) -{ - struct sphw_hwif *hwif = priv_data; - enum sphw_doorbell_ctrl db_ctrl; - - db_ctrl = sphw_get_doorbell_ctrl_status(hwif); - if (db_ctrl == DISABLE_DOORBELL) - return WAIT_PROCESS_CPL; - - return WAIT_PROCESS_WAITING; -} - -int wait_until_doorbell_flush_states(struct sphw_hwif *hwif, - enum sphw_doorbell_ctrl states) -{ - if (!hwif) - return -EFAULT; - - return sphw_wait_for_timeout(hwif, states == ENABLE_DOORBELL ? - check_db_flush_enable_handler : check_db_flush_disable_handler, - SPHW_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT, USEC_PER_MSEC); -} - -static enum sphw_wait_return check_db_outbound_enable_handler(void *priv_data) -{ - struct sphw_hwif *hwif = priv_data; - enum sphw_doorbell_ctrl db_ctrl; - enum sphw_outbound_ctrl outbound_ctrl; - - db_ctrl = sphw_get_doorbell_ctrl_status(hwif); - outbound_ctrl = sphw_get_outbound_ctrl_status(hwif); - - if (outbound_ctrl == ENABLE_OUTBOUND && db_ctrl == ENABLE_DOORBELL) - return WAIT_PROCESS_CPL; - - return WAIT_PROCESS_WAITING; -} - -static int wait_until_doorbell_and_outbound_enabled(struct sphw_hwif *hwif) -{ - return sphw_wait_for_timeout(hwif, check_db_outbound_enable_handler, - SPHW_WAIT_DOORBELL_AND_OUTBOUND_TIMEOUT, USEC_PER_MSEC); -} - -/** - * sphw_init_hwif - initialize the hw interface - * @hwif: the hardware interface of a pci function device - * @pdev: the pci device that will be part of the hwif struct - * Return: 0 - success, negative - failure - **/ -int sphw_init_hwif(struct sphw_hwdev *hwdev, void *cfg_reg_base, void *intr_reg_base, - void *mgmt_regs_base, u64 db_base_phy, void *db_base, u64 db_dwqe_len) -{ - struct sphw_hwif *hwif = NULL; - u32 attr4, attr5; - int err; - - hwif = kzalloc(sizeof(*hwif), GFP_KERNEL); - if (!hwif) - return -ENOMEM; - - hwdev->hwif = hwif; - hwif->pdev = hwdev->pcidev_hdl; - - /* if function is VF, mgmt_regs_base will be NULL */ - if (!mgmt_regs_base) - hwif->cfg_regs_base = (u8 *)cfg_reg_base + - SPHW_VF_CFG_REG_OFFSET; - else - hwif->cfg_regs_base = cfg_reg_base; - - hwif->intr_regs_base = intr_reg_base; - hwif->mgmt_regs_base = mgmt_regs_base; - sdk_info(hwdev->dev_hdl, "init intr_regs_base: %p, mgmt_regs_base: %p, db_base: %p, db_dwqe_len: 0x%llx\n", - hwif->intr_regs_base, hwif->mgmt_regs_base, - db_base, db_dwqe_len); - - hwif->db_base_phy = db_base_phy; - hwif->db_base = db_base; - hwif->db_dwqe_len = db_dwqe_len; - err = init_db_area_idx(&hwif->free_db_area, hwif->db_dwqe_len); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init db area.\n"); - goto init_db_area_err; - } - - err = wait_hwif_ready(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Chip status is not ready\n"); - goto hwif_ready_err; - } - - get_hwif_attr(hwif); - - err = wait_until_doorbell_and_outbound_enabled(hwif); - if (err) { - attr4 = sphw_hwif_read_reg(hwif, SPHW_CSR_FUNC_ATTR4_ADDR); - attr5 = sphw_hwif_read_reg(hwif, SPHW_CSR_FUNC_ATTR5_ADDR); - sdk_err(hwdev->dev_hdl, "Hw doorbell/outbound is disabled, attr4 0x%x attr5 0x%x\n", - attr4, attr5); - goto hwif_ready_err; - } - - if (!SPHW_IS_VF(hwdev)) { - set_ppf(hwif); - - if (SPHW_IS_PPF(hwdev)) - set_mpf(hwif); - - get_mpf(hwif); - } - - disable_all_msix(hwdev); - /* disable mgmt cpu report any event */ - sphw_set_pf_status(hwdev->hwif, SPHW_PF_STATUS_INIT); - - sdk_info(hwdev->dev_hdl, "global_func_idx: %u, func_type: %d, host_id: %u, ppf: %u, mpf: %u\n", - hwif->attr.func_global_idx, hwif->attr.func_type, - hwif->attr.pci_intf_idx, hwif->attr.ppf_idx, - hwif->attr.mpf_idx); - - return 0; - -hwif_ready_err: - free_db_area(&hwif->free_db_area); -init_db_area_err: - kfree(hwif); - - return err; -} - -/** - * sphw_free_hwif - free the hw interface - * @hwif: the hardware interface of a pci function device - * @pdev: the pci device that will be part of the hwif struct - **/ -void sphw_free_hwif(struct sphw_hwdev *hwdev) -{ - free_db_area(&hwdev->hwif->free_db_area); - kfree(hwdev->hwif); -} - -u16 sphw_global_func_id(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.func_global_idx; -} - -u16 sphw_intr_num(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.num_irqs; -} - -u8 sphw_pf_id_of_vf(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.port_to_port_idx; -} - -u8 sphw_pcie_itf_id(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.pci_intf_idx; -} - -u8 sphw_vf_in_pf(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.vf_in_pf; -} - -enum func_type sphw_func_type(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.func_type; -} - -u8 sphw_ceq_num(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.num_ceqs; -} - -u8 sphw_dma_attr_entry_num(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.num_dma_attr; -} - -u16 sphw_glb_pf_vf_offset(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.global_vf_id_of_pf; -} - -u8 sphw_mpf_idx(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.mpf_idx; -} - -u8 sphw_ppf_idx(void *hwdev) -{ - struct sphw_hwif *hwif = NULL; - - if (!hwdev) - return 0; - - hwif = ((struct sphw_hwdev *)hwdev)->hwif; - - return hwif->attr.ppf_idx; -} - -u8 sphw_host_ppf_idx(void *hwdev, u8 host_id) -{ - struct sphw_hwdev *dev = hwdev; - u32 ppf_elect_port_addr; - u32 val; - - if (!hwdev) - return 0; - - ppf_elect_port_addr = SPHW_CSR_FUNC_PPF_ELECT(host_id); - val = sphw_hwif_read_reg(dev->hwif, ppf_elect_port_addr); - - return sphw_PPF_ELECT_PORT_GET(val, IDX); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwif.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwif.h deleted file mode 100644 index 9035baf8a66e..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hwif.h +++ /dev/null @@ -1,102 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_HWIF_H -#define SPHW_HWIF_H - -#define SPHW_PCIE_LINK_DOWN 0xFFFFFFFF - -struct sphw_free_db_area { - unsigned long *db_bitmap_array; - u32 db_max_areas; - /* spinlock for allocating doorbell area */ - spinlock_t idx_lock; -}; - -struct sphw_func_attr { - u16 func_global_idx; - u8 port_to_port_idx; - u8 pci_intf_idx; - u8 vf_in_pf; - enum func_type func_type; - - u8 mpf_idx; - - u8 ppf_idx; - - u16 num_irqs; - u8 num_aeqs; - u8 num_ceqs; - - u8 num_dma_attr; - - u16 global_vf_id_of_pf; -}; - -struct sphw_hwif { - u8 __iomem *cfg_regs_base; - u8 __iomem *intr_regs_base; - u8 __iomem *mgmt_regs_base; - u64 db_base_phy; - u64 db_dwqe_len; - u8 __iomem *db_base; - - struct sphw_free_db_area free_db_area; - - struct sphw_func_attr attr; - - void *pdev; -}; - -enum sphw_outbound_ctrl { - ENABLE_OUTBOUND = 0x0, - DISABLE_OUTBOUND = 0x1, -}; - -enum sphw_doorbell_ctrl { - ENABLE_DOORBELL = 0x0, - DISABLE_DOORBELL = 0x1, -}; - -enum sphw_pf_status { - SPHW_PF_STATUS_INIT = 0X0, - SPHW_PF_STATUS_ACTIVE_FLAG = 0x11, - SPHW_PF_STATUS_FLR_START_FLAG = 0x12, - SPHW_PF_STATUS_FLR_FINISH_FLAG = 0x13, -}; - -#define SPHW_HWIF_NUM_AEQS(hwif) ((hwif)->attr.num_aeqs) -#define SPHW_HWIF_NUM_CEQS(hwif) ((hwif)->attr.num_ceqs) -#define SPHW_HWIF_NUM_IRQS(hwif) ((hwif)->attr.num_irqs) -#define SPHW_HWIF_GLOBAL_IDX(hwif) ((hwif)->attr.func_global_idx) -#define SPHW_HWIF_GLOBAL_VF_OFFSET(hwif) ((hwif)->attr.global_vf_id_of_pf) -#define SPHW_HWIF_PPF_IDX(hwif) ((hwif)->attr.ppf_idx) -#define SPHW_PCI_INTF_IDX(hwif) ((hwif)->attr.pci_intf_idx) - -#define SPHW_FUNC_TYPE(dev) ((dev)->hwif->attr.func_type) -#define SPHW_IS_PF(dev) (SPHW_FUNC_TYPE(dev) == TYPE_PF) -#define SPHW_IS_VF(dev) (SPHW_FUNC_TYPE(dev) == TYPE_VF) -#define SPHW_IS_PPF(dev) (SPHW_FUNC_TYPE(dev) == TYPE_PPF) - -u32 sphw_hwif_read_reg(struct sphw_hwif *hwif, u32 reg); - -void sphw_hwif_write_reg(struct sphw_hwif *hwif, u32 reg, u32 val); - -void sphw_set_pf_status(struct sphw_hwif *hwif, enum sphw_pf_status status); - -enum sphw_pf_status sphw_get_pf_status(struct sphw_hwif *hwif); - -void sphw_disable_doorbell(struct sphw_hwif *hwif); - -void sphw_enable_doorbell(struct sphw_hwif *hwif); - -int sphw_init_hwif(struct sphw_hwdev *hwdev, void *cfg_reg_base, void *intr_reg_base, - void *mgmt_regs_base, u64 db_base_phy, void *db_base, u64 db_dwqe_len); - -void sphw_free_hwif(struct sphw_hwdev *hwdev); - -u8 sphw_host_ppf_idx(void *hwdev, u8 host_id); - -u32 sphw_get_heartbeat_status(struct sphw_hwdev *hwdev); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mbox.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mbox.c deleted file mode 100644 index 694463ca0a93..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mbox.c +++ /dev/null @@ -1,1792 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/types.h> -#include <linux/semaphore.h> -#include <linux/spinlock.h> -#include <linux/workqueue.h> - -#include "sphw_hw.h" -#include "sphw_hwdev.h" -#include "sphw_csr.h" -#include "sphw_hwif.h" -#include "sphw_eqs.h" -#include "sphw_prof_adap.h" -#include "sphw_mbox.h" -#include "sphw_common.h" - -#define SPHW_MBOX_INT_DST_AEQN_SHIFT 10 -#define SPHW_MBOX_INT_SRC_RESP_AEQN_SHIFT 12 -#define SPHW_MBOX_INT_STAT_DMA_SHIFT 14 -/* The size of data to be send (unit of 4 bytes) */ -#define SPHW_MBOX_INT_TX_SIZE_SHIFT 20 -/* SO_RO(strong order, relax order) */ -#define SPHW_MBOX_INT_STAT_DMA_SO_RO_SHIFT 25 -#define SPHW_MBOX_INT_WB_EN_SHIFT 28 - -#define SPHW_MBOX_INT_DST_AEQN_MASK 0x3 -#define SPHW_MBOX_INT_SRC_RESP_AEQN_MASK 0x3 -#define SPHW_MBOX_INT_STAT_DMA_MASK 0x3F -#define SPHW_MBOX_INT_TX_SIZE_MASK 0x1F -#define SPHW_MBOX_INT_STAT_DMA_SO_RO_MASK 0x3 -#define SPHW_MBOX_INT_WB_EN_MASK 0x1 - -#define SPHW_MBOX_INT_SET(val, field) \ - (((val) & SPHW_MBOX_INT_##field##_MASK) << \ - SPHW_MBOX_INT_##field##_SHIFT) - -enum sphw_mbox_tx_status { - TX_NOT_DONE = 1, -}; - -#define SPHW_MBOX_CTRL_TRIGGER_AEQE_SHIFT 0 -/* specifies the issue request for the message data. - * 0 - Tx request is done; - * 1 - Tx request is in process. - */ -#define SPHW_MBOX_CTRL_TX_STATUS_SHIFT 1 -#define SPHW_MBOX_CTRL_DST_FUNC_SHIFT 16 - -#define SPHW_MBOX_CTRL_TRIGGER_AEQE_MASK 0x1 -#define SPHW_MBOX_CTRL_TX_STATUS_MASK 0x1 -#define SPHW_MBOX_CTRL_DST_FUNC_MASK 0x1FFF - -#define SPHW_MBOX_CTRL_SET(val, field) \ - (((val) & SPHW_MBOX_CTRL_##field##_MASK) << \ - SPHW_MBOX_CTRL_##field##_SHIFT) - -#define MBOX_SEGLEN_MASK SPHW_MSG_HEADER_SET(SPHW_MSG_HEADER_SEG_LEN_MASK, SEG_LEN) - -#define MBOX_MSG_POLLING_TIMEOUT 8000 -#define SPHW_MBOX_COMP_TIME 25000U - -#define MBOX_MAX_BUF_SZ 2048U -#define MBOX_HEADER_SZ 8 -#define SPHW_MBOX_DATA_SIZE (MBOX_MAX_BUF_SZ - MBOX_HEADER_SZ) - -/* MBOX size is 64B, 8B for mbox_header, 8B reserved */ -#define MBOX_SEG_LEN 48 -#define MBOX_SEG_LEN_ALIGN 4 -#define MBOX_WB_STATUS_LEN 16UL - -#define SEQ_ID_START_VAL 0 -#define SEQ_ID_MAX_VAL 42 -#define MBOX_LAST_SEG_MAX_LEN (MBOX_MAX_BUF_SZ - \ - SEQ_ID_MAX_VAL * MBOX_SEG_LEN) - -/* mbox write back status is 16B, only first 4B is used */ -#define MBOX_WB_STATUS_ERRCODE_MASK 0xFFFF -#define MBOX_WB_STATUS_MASK 0xFF -#define MBOX_WB_ERROR_CODE_MASK 0xFF00 -#define MBOX_WB_STATUS_FINISHED_SUCCESS 0xFF -#define MBOX_WB_STATUS_FINISHED_WITH_ERR 0xFE -#define MBOX_WB_STATUS_NOT_FINISHED 0x00 - -#define MBOX_STATUS_FINISHED(wb) \ - (((wb) & MBOX_WB_STATUS_MASK) != MBOX_WB_STATUS_NOT_FINISHED) -#define MBOX_STATUS_SUCCESS(wb) \ - (((wb) & MBOX_WB_STATUS_MASK) == MBOX_WB_STATUS_FINISHED_SUCCESS) -#define MBOX_STATUS_ERRCODE(wb) \ - ((wb) & MBOX_WB_ERROR_CODE_MASK) - -#define DST_AEQ_IDX_DEFAULT_VAL 0 -#define SRC_AEQ_IDX_DEFAULT_VAL 0 -#define NO_DMA_ATTRIBUTE_VAL 0 - -#define MBOX_MSG_NO_DATA_LEN 1 - -#define MBOX_BODY_FROM_HDR(header) ((u8 *)(header) + MBOX_HEADER_SZ) -#define MBOX_AREA(hwif) \ - ((hwif)->cfg_regs_base + SPHW_FUNC_CSR_MAILBOX_DATA_OFF) - -#define MBOX_DMA_MSG_QUEUE_DEPTH 32 - -#define MBOX_MQ_CI_OFFSET (SPHW_CFG_REGS_FLAG + SPHW_FUNC_CSR_MAILBOX_DATA_OFF + \ - MBOX_HEADER_SZ + MBOX_SEG_LEN) - -#define MBOX_MQ_SYNC_CI_SHIFT 0 -#define MBOX_MQ_ASYNC_CI_SHIFT 8 - -#define MBOX_MQ_SYNC_CI_MASK 0xFF -#define MBOX_MQ_ASYNC_CI_MASK 0xFF - -#define MBOX_MQ_CI_SET(val, field) \ - (((val) & MBOX_MQ_##field##_CI_MASK) << MBOX_MQ_##field##_CI_SHIFT) -#define MBOX_MQ_CI_GET(val, field) \ - (((val) >> MBOX_MQ_##field##_CI_SHIFT) & MBOX_MQ_##field##_CI_MASK) -#define MBOX_MQ_CI_CLEAR(val, field) \ - ((val) & (~(MBOX_MQ_##field##_CI_MASK << MBOX_MQ_##field##_CI_SHIFT))) - -#define IS_PF_OR_PPF_SRC(hwdev, src_func_idx) \ - ((src_func_idx) < SPHW_MAX_PF_NUM(hwdev)) - -#define MBOX_RESPONSE_ERROR 0x1 -#define MBOX_MSG_ID_MASK 0xF -#define MBOX_MSG_ID(func_to_func) ((func_to_func)->send_msg_id) -#define MBOX_MSG_ID_INC(func_to_func) \ - (MBOX_MSG_ID(func_to_func) = \ - (MBOX_MSG_ID(func_to_func) + 1) & MBOX_MSG_ID_MASK) - -/* max message counter wait to process for one function */ -#define SPHW_MAX_MSG_CNT_TO_PROCESS 10 - -#define MBOX_MSG_CHANNEL_STOP(func_to_func) \ - ((((func_to_func)->lock_channel_en) && \ - test_bit((func_to_func)->cur_msg_channel, \ - &(func_to_func)->channel_stop)) ? true : false) - -enum mbox_ordering_type { - STRONG_ORDER, -}; - -enum mbox_write_back_type { - WRITE_BACK = 1, -}; - -enum mbox_aeq_trig_type { - NOT_TRIGGER, - TRIGGER, -}; - -static int send_mbox_msg(struct sphw_mbox *func_to_func, u8 mod, u16 cmd, - void *msg, u16 msg_len, u16 dst_func, - enum sphw_msg_direction_type direction, - enum sphw_msg_ack_type ack_type, - struct mbox_msg_info *msg_info); - -struct sphw_msg_desc *get_mbox_msg_desc(struct sphw_mbox *func_to_func, - u64 dir, u64 src_func_id); - -/** - * sphw_register_ppf_mbox_cb - register mbox callback for ppf - * @hwdev: the pointer to hw device - * @mod: specific mod that the callback will handle - * @pri_handle specific mod's private data that will be used in callback - * @callback: callback function - * Return: 0 - success, negative - failure - */ -int sphw_register_ppf_mbox_cb(void *hwdev, u8 mod, void *pri_handle, sphw_ppf_mbox_cb callback) -{ - struct sphw_mbox *func_to_func = NULL; - - if (mod >= SPHW_MOD_MAX || !hwdev) - return -EFAULT; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - - func_to_func->ppf_mbox_cb[mod] = callback; - func_to_func->ppf_mbox_data[mod] = pri_handle; - - set_bit(SPHW_PPF_MBOX_CB_REG, &func_to_func->ppf_mbox_cb_state[mod]); - - return 0; -} - -/** - * sphw_register_pf_mbox_cb - register mbox callback for pf - * @hwdev: the pointer to hw device - * @mod: specific mod that the callback will handle - * @pri_handle specific mod's private data that will be used in callback - * @callback: callback function - * Return: 0 - success, negative - failure - */ -int sphw_register_pf_mbox_cb(void *hwdev, u8 mod, void *pri_handle, sphw_pf_mbox_cb callback) -{ - struct sphw_mbox *func_to_func = NULL; - - if (mod >= SPHW_MOD_MAX || !hwdev) - return -EFAULT; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - - func_to_func->pf_mbox_cb[mod] = callback; - func_to_func->pf_mbox_data[mod] = pri_handle; - - set_bit(SPHW_PF_MBOX_CB_REG, &func_to_func->pf_mbox_cb_state[mod]); - - return 0; -} - -/** - * sphw_register_vf_mbox_cb - register mbox callback for vf - * @hwdev: the pointer to hw device - * @mod: specific mod that the callback will handle - * @pri_handle specific mod's private data that will be used in callback - * @callback: callback function - * Return: 0 - success, negative - failure - */ -int sphw_register_vf_mbox_cb(void *hwdev, u8 mod, void *pri_handle, sphw_vf_mbox_cb callback) -{ - struct sphw_mbox *func_to_func = NULL; - - if (mod >= SPHW_MOD_MAX || !hwdev) - return -EFAULT; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - - func_to_func->vf_mbox_cb[mod] = callback; - func_to_func->vf_mbox_data[mod] = pri_handle; - - set_bit(SPHW_VF_MBOX_CB_REG, &func_to_func->vf_mbox_cb_state[mod]); - - return 0; -} - -/** - * sphw_register_ppf_to_pf_mbox_cb - register mbox callback for pf from ppf - * @hwdev: the pointer to hw device - * @mod: specific mod that the callback will handle - * @pri_handle specific mod's private data that will be used in callback - * @callback: callback function - * Return: 0 - success, negative - failure - */ -int sphw_register_ppf_to_pf_mbox_cb(void *hwdev, u8 mod, void *pri_handle, - sphw_pf_recv_from_ppf_mbox_cb callback) -{ - struct sphw_mbox *func_to_func = NULL; - - if (mod >= SPHW_MOD_MAX || !hwdev) - return -EFAULT; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - - func_to_func->pf_recv_ppf_mbox_cb[mod] = callback; - func_to_func->pf_recv_ppf_mbox_data[mod] = pri_handle; - - set_bit(SPHW_PPF_TO_PF_MBOX_CB_REG, - &func_to_func->ppf_to_pf_mbox_cb_state[mod]); - - return 0; -} - -/** - * sphw_unregister_ppf_mbox_cb - unregister the mbox callback for ppf - * @hwdev: the pointer to hw device - * @mod: specific mod that the callback will handle - * Return: - */ -void sphw_unregister_ppf_mbox_cb(void *hwdev, u8 mod) -{ - struct sphw_mbox *func_to_func = NULL; - - if (mod >= SPHW_MOD_MAX || !hwdev) - return; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - - clear_bit(SPHW_PPF_MBOX_CB_REG, - &func_to_func->ppf_mbox_cb_state[mod]); - - while (test_bit(SPHW_PPF_MBOX_CB_RUNNING, - &func_to_func->ppf_mbox_cb_state[mod])) - usleep_range(900, 1000); - - func_to_func->ppf_mbox_data[mod] = NULL; - func_to_func->ppf_mbox_cb[mod] = NULL; -} - -/** - * sphw_unregister_ppf_mbox_cb - unregister the mbox callback for pf - * @hwdev: the pointer to hw device - * @mod: specific mod that the callback will handle - * Return: - */ -void sphw_unregister_pf_mbox_cb(void *hwdev, u8 mod) -{ - struct sphw_mbox *func_to_func = NULL; - - if (mod >= SPHW_MOD_MAX || !hwdev) - return; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - - clear_bit(SPHW_PF_MBOX_CB_REG, &func_to_func->pf_mbox_cb_state[mod]); - - while (test_bit(SPHW_PF_MBOX_CB_RUNNING, - &func_to_func->pf_mbox_cb_state[mod])) - usleep_range(900, 1000); - - func_to_func->pf_mbox_data[mod] = NULL; - func_to_func->pf_mbox_cb[mod] = NULL; -} - -/** - * sphw_unregister_vf_mbox_cb - unregister the mbox callback for vf - * @hwdev: the pointer to hw device - * @mod: specific mod that the callback will handle - * Return: - */ -void sphw_unregister_vf_mbox_cb(void *hwdev, u8 mod) -{ - struct sphw_mbox *func_to_func = NULL; - - if (mod >= SPHW_MOD_MAX || !hwdev) - return; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - - clear_bit(SPHW_VF_MBOX_CB_REG, &func_to_func->vf_mbox_cb_state[mod]); - - while (test_bit(SPHW_VF_MBOX_CB_RUNNING, - &func_to_func->vf_mbox_cb_state[mod])) - usleep_range(900, 1000); - - func_to_func->vf_mbox_data[mod] = NULL; - func_to_func->vf_mbox_cb[mod] = NULL; -} - -/** - * sphw_unregister_ppf_mbox_cb - unregister the mbox callback for pf from ppf - * @hwdev: the pointer to hw device - * @mod: specific mod that the callback will handle - * Return: - */ -void sphw_unregister_ppf_to_pf_mbox_cb(void *hwdev, u8 mod) -{ - struct sphw_mbox *func_to_func = NULL; - - if (mod >= SPHW_MOD_MAX || !hwdev) - return; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - - clear_bit(SPHW_PPF_TO_PF_MBOX_CB_REG, - &func_to_func->ppf_to_pf_mbox_cb_state[mod]); - - while (test_bit(SPHW_PPF_TO_PF_MBOX_CB_RUNNIG, - &func_to_func->ppf_to_pf_mbox_cb_state[mod])) - usleep_range(900, 1000); - - func_to_func->pf_recv_ppf_mbox_data[mod] = NULL; - func_to_func->pf_recv_ppf_mbox_cb[mod] = NULL; -} - -static int recv_vf_mbox_handler(struct sphw_mbox *func_to_func, - struct sphw_recv_mbox *recv_mbox, - void *buf_out, u16 *out_size) -{ - sphw_vf_mbox_cb cb; - int ret; - - if (recv_mbox->mod >= SPHW_MOD_MAX) { - sdk_warn(func_to_func->hwdev->dev_hdl, "Receive illegal mbox message, mod = %hhu\n", - recv_mbox->mod); - return -EINVAL; - } - - set_bit(SPHW_VF_MBOX_CB_RUNNING, &func_to_func->vf_mbox_cb_state[recv_mbox->mod]); - - cb = func_to_func->vf_mbox_cb[recv_mbox->mod]; - if (cb && test_bit(SPHW_VF_MBOX_CB_REG, - &func_to_func->vf_mbox_cb_state[recv_mbox->mod])) { - ret = cb(func_to_func->hwdev, - func_to_func->vf_mbox_data[recv_mbox->mod], - recv_mbox->cmd, recv_mbox->msg, - recv_mbox->msg_len, buf_out, out_size); - } else { - sdk_warn(func_to_func->hwdev->dev_hdl, "VF mbox cb is not registered\n"); - ret = -EINVAL; - } - - clear_bit(SPHW_VF_MBOX_CB_RUNNING, - &func_to_func->vf_mbox_cb_state[recv_mbox->mod]); - - return ret; -} - -static int recv_pf_from_ppf_handler(struct sphw_mbox *func_to_func, - struct sphw_recv_mbox *recv_mbox, - void *buf_out, u16 *out_size) -{ - sphw_pf_recv_from_ppf_mbox_cb cb; - enum sphw_mod_type mod = recv_mbox->mod; - int ret; - - if (mod >= SPHW_MOD_MAX) { - sdk_warn(func_to_func->hwdev->dev_hdl, "Receive illegal mbox message, mod = %d\n", - mod); - return -EINVAL; - } - - set_bit(SPHW_PPF_TO_PF_MBOX_CB_RUNNIG, - &func_to_func->ppf_to_pf_mbox_cb_state[mod]); - - cb = func_to_func->pf_recv_ppf_mbox_cb[mod]; - if (cb && test_bit(SPHW_PPF_TO_PF_MBOX_CB_REG, - &func_to_func->ppf_to_pf_mbox_cb_state[mod])) { - ret = cb(func_to_func->hwdev, - func_to_func->pf_recv_ppf_mbox_data[mod], - recv_mbox->cmd, recv_mbox->msg, recv_mbox->msg_len, - buf_out, out_size); - } else { - sdk_warn(func_to_func->hwdev->dev_hdl, "PF receive ppf mailbox callback is not registered\n"); - ret = -EINVAL; - } - - clear_bit(SPHW_PPF_TO_PF_MBOX_CB_RUNNIG, - &func_to_func->ppf_to_pf_mbox_cb_state[mod]); - - return ret; -} - -static int recv_ppf_mbox_handler(struct sphw_mbox *func_to_func, - struct sphw_recv_mbox *recv_mbox, - u8 pf_id, void *buf_out, u16 *out_size) -{ - sphw_ppf_mbox_cb cb; - u16 vf_id = 0; - int ret; - - if (recv_mbox->mod >= SPHW_MOD_MAX) { - sdk_warn(func_to_func->hwdev->dev_hdl, "Receive illegal mbox message, mod = %hhu\n", - recv_mbox->mod); - return -EINVAL; - } - - set_bit(SPHW_PPF_MBOX_CB_RUNNING, - &func_to_func->ppf_mbox_cb_state[recv_mbox->mod]); - - cb = func_to_func->ppf_mbox_cb[recv_mbox->mod]; - if (cb && test_bit(SPHW_PPF_MBOX_CB_REG, - &func_to_func->ppf_mbox_cb_state[recv_mbox->mod])) { - ret = cb(func_to_func->hwdev, - func_to_func->ppf_mbox_data[recv_mbox->mod], - pf_id, vf_id, recv_mbox->cmd, recv_mbox->msg, - recv_mbox->msg_len, buf_out, out_size); - } else { - sdk_warn(func_to_func->hwdev->dev_hdl, "PPF mbox cb is not registered, mod = %hhu\n", - recv_mbox->mod); - ret = -EINVAL; - } - - clear_bit(SPHW_PPF_MBOX_CB_RUNNING, - &func_to_func->ppf_mbox_cb_state[recv_mbox->mod]); - - return ret; -} - -static int recv_pf_from_vf_mbox_handler(struct sphw_mbox *func_to_func, - struct sphw_recv_mbox *recv_mbox, - u16 src_func_idx, void *buf_out, - u16 *out_size) -{ - sphw_pf_mbox_cb cb; - u16 vf_id = 0; - int ret; - - if (recv_mbox->mod >= SPHW_MOD_MAX) { - sdk_warn(func_to_func->hwdev->dev_hdl, "Receive illegal mbox message, mod = %hhu\n", - recv_mbox->mod); - return -EINVAL; - } - - set_bit(SPHW_PF_MBOX_CB_RUNNING, - &func_to_func->pf_mbox_cb_state[recv_mbox->mod]); - - cb = func_to_func->pf_mbox_cb[recv_mbox->mod]; - if (cb && test_bit(SPHW_PF_MBOX_CB_REG, - &func_to_func->pf_mbox_cb_state[recv_mbox->mod])) { - vf_id = src_func_idx - - sphw_glb_pf_vf_offset(func_to_func->hwdev); - ret = cb(func_to_func->hwdev, - func_to_func->pf_mbox_data[recv_mbox->mod], - vf_id, recv_mbox->cmd, recv_mbox->msg, - recv_mbox->msg_len, buf_out, out_size); - } else { - sdk_warn(func_to_func->hwdev->dev_hdl, "PF mbox mod(0x%x) cb is not registered\n", - recv_mbox->mod); - ret = -EINVAL; - } - - clear_bit(SPHW_PF_MBOX_CB_RUNNING, - &func_to_func->pf_mbox_cb_state[recv_mbox->mod]); - - return ret; -} - -static void response_for_recv_func_mbox(struct sphw_mbox *func_to_func, - struct sphw_recv_mbox *recv_mbox, - int err, u16 out_size, u16 src_func_idx) -{ - struct mbox_msg_info msg_info = {0}; - - msg_info.msg_id = recv_mbox->msg_id; - if (err) - msg_info.status = SPHW_MBOX_PF_SEND_ERR; - - /* if not data need to response, set out_size to 1 */ - if (!out_size || err) - out_size = MBOX_MSG_NO_DATA_LEN; - - send_mbox_msg(func_to_func, recv_mbox->mod, recv_mbox->cmd, - recv_mbox->resp_buff, out_size, src_func_idx, - SPHW_MSG_RESPONSE, SPHW_MSG_NO_ACK, &msg_info); -} - -static void recv_func_mbox_handler(struct sphw_mbox *func_to_func, - struct sphw_recv_mbox *recv_mbox) -{ - struct sphw_hwdev *dev = func_to_func->hwdev; - void *buf_out = recv_mbox->resp_buff; - u16 src_func_idx = recv_mbox->src_func_idx; - u16 out_size = MBOX_MAX_BUF_SZ; - int err = 0; - - if (SPHW_IS_VF(dev)) { - err = recv_vf_mbox_handler(func_to_func, recv_mbox, buf_out, - &out_size); - } else { /* pf/ppf process */ - if (IS_PF_OR_PPF_SRC(dev, src_func_idx)) { - if (SPHW_IS_PPF(dev)) { - err = recv_ppf_mbox_handler(func_to_func, - recv_mbox, - (u8)src_func_idx, - buf_out, &out_size); - if (err) - goto out; - } else { - err = recv_pf_from_ppf_handler(func_to_func, - recv_mbox, - buf_out, - &out_size); - if (err) - goto out; - } - /* The source is neither PF nor PPF, so it is from VF */ - } else { - err = recv_pf_from_vf_mbox_handler(func_to_func, - recv_mbox, - src_func_idx, - buf_out, &out_size); - } - } - -out: - if (recv_mbox->ack_type == SPHW_MSG_ACK) - response_for_recv_func_mbox(func_to_func, recv_mbox, err, - out_size, src_func_idx); -} - -static struct sphw_recv_mbox *alloc_recv_mbox(void) -{ - struct sphw_recv_mbox *recv_msg = NULL; - - recv_msg = kzalloc(sizeof(*recv_msg), GFP_KERNEL); - if (!recv_msg) - return NULL; - - recv_msg->msg = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL); - if (!recv_msg->msg) - goto alloc_msg_err; - - recv_msg->resp_buff = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL); - if (!recv_msg->resp_buff) - goto alloc_resp_bff_err; - - return recv_msg; - -alloc_resp_bff_err: - kfree(recv_msg->msg); - -alloc_msg_err: - kfree(recv_msg); - - return NULL; -} - -static void free_recv_mbox(struct sphw_recv_mbox *recv_msg) -{ - kfree(recv_msg->resp_buff); - kfree(recv_msg->msg); - kfree(recv_msg); -} - -static void recv_func_mbox_work_handler(struct work_struct *work) -{ - struct sphw_mbox_work *mbox_work = - container_of(work, struct sphw_mbox_work, work); - - recv_func_mbox_handler(mbox_work->func_to_func, mbox_work->recv_mbox); - - atomic_dec(&mbox_work->msg_ch->recv_msg_cnt); - - free_recv_mbox(mbox_work->recv_mbox); - kfree(mbox_work); -} - -static void resp_mbox_handler(struct sphw_mbox *func_to_func, - struct sphw_msg_desc *msg_desc) -{ - spin_lock(&func_to_func->mbox_lock); - if (msg_desc->msg_info.msg_id == func_to_func->send_msg_id && - func_to_func->event_flag == EVENT_START) - func_to_func->event_flag = EVENT_SUCCESS; - else - sdk_err(func_to_func->hwdev->dev_hdl, - "Mbox response timeout, current send msg id(0x%x), recv msg id(0x%x), status(0x%x)\n", - func_to_func->send_msg_id, msg_desc->msg_info.msg_id, - msg_desc->msg_info.status); - spin_unlock(&func_to_func->mbox_lock); -} - -static void recv_mbox_msg_handler(struct sphw_mbox *func_to_func, - struct sphw_msg_desc *msg_desc, - u64 mbox_header) -{ - struct sphw_hwdev *hwdev = func_to_func->hwdev; - struct sphw_recv_mbox *recv_msg = NULL; - struct sphw_mbox_work *mbox_work = NULL; - struct sphw_msg_channel *msg_ch = - container_of(msg_desc, struct sphw_msg_channel, recv_msg); - u16 src_func_idx = SPHW_MSG_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX); - - if (atomic_read(&msg_ch->recv_msg_cnt) > - SPHW_MAX_MSG_CNT_TO_PROCESS) { - sdk_warn(hwdev->dev_hdl, "This function(%u) have %d message wait to process, can't add to work queue\n", - src_func_idx, atomic_read(&msg_ch->recv_msg_cnt)); - return; - } - - recv_msg = alloc_recv_mbox(); - if (!recv_msg) { - sdk_err(hwdev->dev_hdl, "Failed to alloc receive mbox message buffer\n"); - return; - } - recv_msg->msg_len = msg_desc->msg_len; - memcpy(recv_msg->msg, msg_desc->msg, recv_msg->msg_len); - recv_msg->msg_id = msg_desc->msg_info.msg_id; - recv_msg->mod = SPHW_MSG_HEADER_GET(mbox_header, MODULE); - recv_msg->cmd = SPHW_MSG_HEADER_GET(mbox_header, CMD); - recv_msg->ack_type = SPHW_MSG_HEADER_GET(mbox_header, NO_ACK); - recv_msg->src_func_idx = src_func_idx; - - mbox_work = kzalloc(sizeof(*mbox_work), GFP_KERNEL); - if (!mbox_work) { - sdk_err(hwdev->dev_hdl, "Allocate mbox work memory failed.\n"); - free_recv_mbox(recv_msg); - return; - } - - atomic_inc(&msg_ch->recv_msg_cnt); - - mbox_work->func_to_func = func_to_func; - mbox_work->recv_mbox = recv_msg; - mbox_work->msg_ch = msg_ch; - - INIT_WORK(&mbox_work->work, recv_func_mbox_work_handler); - queue_work_on(sphw_get_work_cpu_affinity(hwdev, WORK_TYPE_MBOX), - func_to_func->workq, &mbox_work->work); -} - -static bool check_mbox_segment(struct sphw_mbox *func_to_func, - struct sphw_msg_desc *msg_desc, - u64 mbox_header) -{ - u8 seq_id, seg_len, msg_id, mod; - u16 src_func_idx, cmd; - - seq_id = SPHW_MSG_HEADER_GET(mbox_header, SEQID); - seg_len = SPHW_MSG_HEADER_GET(mbox_header, SEG_LEN); - msg_id = SPHW_MSG_HEADER_GET(mbox_header, MSG_ID); - mod = SPHW_MSG_HEADER_GET(mbox_header, MODULE); - cmd = SPHW_MSG_HEADER_GET(mbox_header, CMD); - src_func_idx = SPHW_MSG_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX); - - if (seq_id > SEQ_ID_MAX_VAL || seg_len > MBOX_SEG_LEN || - (seq_id == SEQ_ID_MAX_VAL && seg_len > MBOX_LAST_SEG_MAX_LEN)) - goto seg_err; - - if (seq_id == 0) { - msg_desc->seq_id = seq_id; - msg_desc->msg_info.msg_id = msg_id; - msg_desc->mod = mod; - msg_desc->cmd = cmd; - } else { - if (seq_id != msg_desc->seq_id + 1 || - msg_id != msg_desc->msg_info.msg_id || - mod != msg_desc->mod || cmd != msg_desc->cmd) - goto seg_err; - - msg_desc->seq_id = seq_id; - } - - return true; - -seg_err: - sdk_err(func_to_func->hwdev->dev_hdl, - "Mailbox segment check failed, src func id: 0x%x, front seg info: seq id: 0x%x, msg id: 0x%x, mod: 0x%x, cmd: 0x%x\n", - src_func_idx, msg_desc->seq_id, msg_desc->msg_info.msg_id, - msg_desc->mod, msg_desc->cmd); - sdk_err(func_to_func->hwdev->dev_hdl, - "Current seg info: seg len: 0x%x, seq id: 0x%x, msg id: 0x%x, mod: 0x%x, cmd: 0x%x\n", - seg_len, seq_id, msg_id, mod, cmd); - - return false; -} - -static void recv_mbox_handler(struct sphw_mbox *func_to_func, - void *header, struct sphw_msg_desc *msg_desc) -{ - u64 mbox_header = *((u64 *)header); - void *mbox_body = MBOX_BODY_FROM_HDR(header); - u8 seq_id, seg_len; - int pos; - - if (!check_mbox_segment(func_to_func, msg_desc, mbox_header)) { - msg_desc->seq_id = SEQ_ID_MAX_VAL; - return; - } - - seq_id = SPHW_MSG_HEADER_GET(mbox_header, SEQID); - seg_len = SPHW_MSG_HEADER_GET(mbox_header, SEG_LEN); - - pos = seq_id * MBOX_SEG_LEN; - memcpy((u8 *)msg_desc->msg + pos, mbox_body, seg_len); - - if (!SPHW_MSG_HEADER_GET(mbox_header, LAST)) - return; - - msg_desc->msg_len = SPHW_MSG_HEADER_GET(mbox_header, MSG_LEN); - msg_desc->msg_info.status = SPHW_MSG_HEADER_GET(mbox_header, STATUS); - - if (SPHW_MSG_HEADER_GET(mbox_header, DIRECTION) == - SPHW_MSG_RESPONSE) { - resp_mbox_handler(func_to_func, msg_desc); - return; - } - - recv_mbox_msg_handler(func_to_func, msg_desc, mbox_header); -} - -void sphw_mbox_func_aeqe_handler(void *handle, u8 *header, u8 size) -{ - struct sphw_mbox *func_to_func = NULL; - struct sphw_msg_desc *msg_desc = NULL; - u64 mbox_header = *((u64 *)header); - u64 src, dir; - - func_to_func = ((struct sphw_hwdev *)handle)->func_to_func; - - dir = SPHW_MSG_HEADER_GET(mbox_header, DIRECTION); - src = SPHW_MSG_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX); - - msg_desc = get_mbox_msg_desc(func_to_func, dir, src); - if (!msg_desc) { - sdk_err(func_to_func->hwdev->dev_hdl, - "Mailbox source function id: %u is invalid for current function\n", - (u32)src); - return; - } - - recv_mbox_handler(func_to_func, (u64 *)header, msg_desc); -} - -static int init_mbox_dma_queue(struct sphw_hwdev *hwdev, struct mbox_dma_queue *mq) -{ - u32 size; - - mq->depth = MBOX_DMA_MSG_QUEUE_DEPTH; - mq->prod_idx = 0; - mq->cons_idx = 0; - - size = mq->depth * MBOX_MAX_BUF_SZ; - mq->dma_buff_vaddr = dma_alloc_coherent(hwdev->dev_hdl, size, &mq->dma_buff_paddr, - GFP_KERNEL); - if (!mq->dma_buff_vaddr) { - sdk_err(hwdev->dev_hdl, "Failed to alloc dma_buffer\n"); - return -ENOMEM; - } - - return 0; -} - -static void deinit_mbox_dma_queue(struct sphw_hwdev *hwdev, struct mbox_dma_queue *mq) -{ - dma_free_coherent(hwdev->dev_hdl, mq->depth * MBOX_MAX_BUF_SZ, - mq->dma_buff_vaddr, mq->dma_buff_paddr); -} - -static int sphw_init_mbox_dma_queue(struct sphw_mbox *func_to_func) -{ - u32 val; - int err; - - err = init_mbox_dma_queue(func_to_func->hwdev, &func_to_func->sync_msg_queue); - if (err) - return err; - - err = init_mbox_dma_queue(func_to_func->hwdev, &func_to_func->async_msg_queue); - if (err) { - deinit_mbox_dma_queue(func_to_func->hwdev, &func_to_func->sync_msg_queue); - return err; - } - - val = sphw_hwif_read_reg(func_to_func->hwdev->hwif, MBOX_MQ_CI_OFFSET); - val = MBOX_MQ_CI_CLEAR(val, SYNC); - val = MBOX_MQ_CI_CLEAR(val, ASYNC); - sphw_hwif_write_reg(func_to_func->hwdev->hwif, MBOX_MQ_CI_OFFSET, val); - - return 0; -} - -static void sphw_deinit_mbox_dma_queue(struct sphw_mbox *func_to_func) -{ - deinit_mbox_dma_queue(func_to_func->hwdev, &func_to_func->sync_msg_queue); - deinit_mbox_dma_queue(func_to_func->hwdev, &func_to_func->async_msg_queue); -} - -#define MBOX_DMA_MSG_INIT_XOR_VAL 0x5a5a5a5a -static u32 mbox_dma_msg_xor(u32 *data, u16 msg_len) -{ - u32 xor = MBOX_DMA_MSG_INIT_XOR_VAL; - u16 dw_len = msg_len / sizeof(u32); - u16 i; - - for (i = 0; i < dw_len; i++) - xor ^= data[i]; - - return xor; -} - -#define MQ_ID_MASK(mq, idx) ((idx) & ((mq)->depth - 1)) -#define IS_MSG_QUEUE_FULL(mq) (MQ_ID_MASK(mq, (mq)->prod_idx + 1) == \ - MQ_ID_MASK(mq, (mq)->cons_idx)) - -static int mbox_prepare_dma_entry(struct sphw_mbox *func_to_func, struct mbox_dma_queue *mq, - struct mbox_dma_msg *dma_msg, void *msg, u16 msg_len) -{ - u64 dma_addr, offset; - void *dma_vaddr; - - if (IS_MSG_QUEUE_FULL(mq)) { - sdk_err(func_to_func->hwdev->dev_hdl, "Mbox sync message queue is busy, pi: %u, ci: %u\n", - mq->prod_idx, MQ_ID_MASK(mq, mq->cons_idx)); - return -EBUSY; - } - - /* copy data to DMA buffer */ - offset = mq->prod_idx * MBOX_MAX_BUF_SZ; - dma_vaddr = (u8 *)mq->dma_buff_vaddr + offset; - memcpy(dma_vaddr, msg, msg_len); - dma_addr = mq->dma_buff_paddr + offset; - dma_msg->dma_addr_high = upper_32_bits(dma_addr); - dma_msg->dma_addr_low = lower_32_bits(dma_addr); - dma_msg->msg_len = msg_len; - dma_msg->xor = mbox_dma_msg_xor(dma_vaddr, ALIGN(msg_len, sizeof(u32))); - - mq->prod_idx++; - mq->prod_idx = MQ_ID_MASK(mq, mq->prod_idx); - - return 0; -} - -static int mbox_prepare_dma_msg(struct sphw_mbox *func_to_func, enum sphw_msg_ack_type ack_type, - struct mbox_dma_msg *dma_msg, void *msg, u16 msg_len) -{ - struct mbox_dma_queue *mq = NULL; - u32 val; - - val = sphw_hwif_read_reg(func_to_func->hwdev->hwif, MBOX_MQ_CI_OFFSET); - if (ack_type == SPHW_MSG_ACK) { - mq = &func_to_func->sync_msg_queue; - mq->cons_idx = MBOX_MQ_CI_GET(val, SYNC); - } else { - mq = &func_to_func->async_msg_queue; - mq->cons_idx = MBOX_MQ_CI_GET(val, ASYNC); - } - - return mbox_prepare_dma_entry(func_to_func, mq, dma_msg, msg, msg_len); -} - -static void clear_mbox_status(struct sphw_send_mbox *mbox) -{ - *mbox->wb_status = 0; - - /* clear mailbox write back status */ - wmb(); -} - -static void mbox_copy_header(struct sphw_hwdev *hwdev, - struct sphw_send_mbox *mbox, u64 *header) -{ - u32 *data = (u32 *)header; - u32 i, idx_max = MBOX_HEADER_SZ / sizeof(u32); - - for (i = 0; i < idx_max; i++) - __raw_writel(cpu_to_be32(*(data + i)), mbox->data + i * sizeof(u32)); -} - -static void mbox_copy_send_data(struct sphw_hwdev *hwdev, struct sphw_send_mbox *mbox, void *seg, - u16 seg_len) -{ - u32 *data = seg; - u32 data_len, chk_sz = sizeof(u32); - u32 i, idx_max; - - data_len = seg_len; - idx_max = ALIGN(data_len, chk_sz) / chk_sz; - - for (i = 0; i < idx_max; i++) - __raw_writel(cpu_to_be32(*(data + i)), - mbox->data + MBOX_HEADER_SZ + i * sizeof(u32)); -} - -static void write_mbox_msg_attr(struct sphw_mbox *func_to_func, - u16 dst_func, u16 dst_aeqn, u16 seg_len) -{ - u32 mbox_int, mbox_ctrl; - - /* for VF to PF's message, dest func id will self-learning by HW */ - if (SPHW_IS_VF(func_to_func->hwdev) && - dst_func != SPHW_MGMT_SRC_ID) - dst_func = 0; /* the destination is the VF's PF */ - - mbox_int = SPHW_MBOX_INT_SET(dst_aeqn, DST_AEQN) | - SPHW_MBOX_INT_SET(0, SRC_RESP_AEQN) | - SPHW_MBOX_INT_SET(NO_DMA_ATTRIBUTE_VAL, STAT_DMA) | - SPHW_MBOX_INT_SET(ALIGN(seg_len + MBOX_HEADER_SZ, - MBOX_SEG_LEN_ALIGN) >> 2, TX_SIZE) | - SPHW_MBOX_INT_SET(STRONG_ORDER, STAT_DMA_SO_RO) | - SPHW_MBOX_INT_SET(WRITE_BACK, WB_EN); - - sphw_hwif_write_reg(func_to_func->hwdev->hwif, SPHW_FUNC_CSR_MAILBOX_INT_OFFSET_OFF, - mbox_int); - - wmb(); /* writing the mbox int attributes */ - mbox_ctrl = SPHW_MBOX_CTRL_SET(TX_NOT_DONE, TX_STATUS); - - mbox_ctrl |= SPHW_MBOX_CTRL_SET(NOT_TRIGGER, TRIGGER_AEQE); - - mbox_ctrl |= SPHW_MBOX_CTRL_SET(dst_func, DST_FUNC); - - sphw_hwif_write_reg(func_to_func->hwdev->hwif, - SPHW_FUNC_CSR_MAILBOX_CONTROL_OFF, mbox_ctrl); -} - -void dump_mbox_reg(struct sphw_hwdev *hwdev) -{ - u32 val; - - val = sphw_hwif_read_reg(hwdev->hwif, SPHW_FUNC_CSR_MAILBOX_CONTROL_OFF); - sdk_err(hwdev->dev_hdl, "Mailbox control reg: 0x%x\n", val); - val = sphw_hwif_read_reg(hwdev->hwif, SPHW_FUNC_CSR_MAILBOX_INT_OFFSET_OFF); - sdk_err(hwdev->dev_hdl, "Mailbox interrupt offset: 0x%x\n", val); -} - -static u16 get_mbox_status(struct sphw_send_mbox *mbox) -{ - /* write back is 16B, but only use first 4B */ - u64 wb_val = be64_to_cpu(*mbox->wb_status); - - rmb(); /* verify reading before check */ - - return (u16)(wb_val & MBOX_WB_STATUS_ERRCODE_MASK); -} - -enum sphw_wait_return check_mbox_wb_status(void *priv_data) -{ - struct sphw_mbox *func_to_func = priv_data; - u16 wb_status; - - if (MBOX_MSG_CHANNEL_STOP(func_to_func)) - return WAIT_PROCESS_ERR; - - wb_status = get_mbox_status(&func_to_func->send_mbox); - - return MBOX_STATUS_FINISHED(wb_status) ? - WAIT_PROCESS_CPL : WAIT_PROCESS_WAITING; -} - -static int send_mbox_seg(struct sphw_mbox *func_to_func, u64 header, - u16 dst_func, void *seg, u16 seg_len, void *msg_info) -{ - struct sphw_send_mbox *send_mbox = &func_to_func->send_mbox; - struct sphw_hwdev *hwdev = func_to_func->hwdev; - u8 num_aeqs = hwdev->hwif->attr.num_aeqs; - u16 dst_aeqn, wb_status = 0, errcode; - u16 seq_dir = SPHW_MSG_HEADER_GET(header, DIRECTION); - int err; - - /* mbox to mgmt cpu, hardware don't care dst aeq id*/ - if (num_aeqs > SPHW_MBOX_RSP_MSG_AEQ) - dst_aeqn = (seq_dir == SPHW_MSG_DIRECT_SEND) ? - SPHW_ASYNC_MSG_AEQ : SPHW_MBOX_RSP_MSG_AEQ; - else - dst_aeqn = 0; - - clear_mbox_status(send_mbox); - - mbox_copy_header(hwdev, send_mbox, &header); - - mbox_copy_send_data(hwdev, send_mbox, seg, seg_len); - - write_mbox_msg_attr(func_to_func, dst_func, dst_aeqn, seg_len); - - wmb(); /* writing the mbox msg attributes */ - - err = sphw_wait_for_timeout(func_to_func, check_mbox_wb_status, - MBOX_MSG_POLLING_TIMEOUT, USEC_PER_MSEC); - wb_status = get_mbox_status(send_mbox); - if (err) { - sdk_err(hwdev->dev_hdl, "Send mailbox segment timeout, wb status: 0x%x\n", - wb_status); - dump_mbox_reg(hwdev); - return -ETIMEDOUT; - } - - if (!MBOX_STATUS_SUCCESS(wb_status)) { - sdk_err(hwdev->dev_hdl, "Send mailbox segment to function %u error, wb status: 0x%x\n", - dst_func, wb_status); - errcode = MBOX_STATUS_ERRCODE(wb_status); - return errcode ? errcode : -EFAULT; - } - - return 0; -} - -static int send_mbox_msg(struct sphw_mbox *func_to_func, u8 mod, u16 cmd, - void *msg, u16 msg_len, u16 dst_func, - enum sphw_msg_direction_type direction, - enum sphw_msg_ack_type ack_type, - struct mbox_msg_info *msg_info) -{ - struct sphw_hwdev *hwdev = func_to_func->hwdev; - struct mbox_dma_msg dma_msg = {0}; - enum sphw_data_type data_type = SPHW_DATA_INLINE; - int err = 0; - u32 seq_id = 0; - u16 seg_len = MBOX_SEG_LEN; - u16 rsp_aeq_id, left; - u8 *msg_seg = NULL; - u64 header = 0; - - if (hwdev->hwif->attr.num_aeqs >= 2) - rsp_aeq_id = SPHW_MBOX_RSP_MSG_AEQ; - else - rsp_aeq_id = 0; - - mutex_lock(&func_to_func->msg_send_lock); - - if (IS_DMA_MBX_MSG(dst_func)) { - err = mbox_prepare_dma_msg(func_to_func, ack_type, &dma_msg, msg, msg_len); - if (err) - goto send_err; - - msg = &dma_msg; - msg_len = sizeof(dma_msg); - data_type = SPHW_DATA_DMA; - } - - msg_seg = (u8 *)msg; - left = msg_len; - - header = SPHW_MSG_HEADER_SET(msg_len, MSG_LEN) | - SPHW_MSG_HEADER_SET(mod, MODULE) | - SPHW_MSG_HEADER_SET(seg_len, SEG_LEN) | - SPHW_MSG_HEADER_SET(ack_type, NO_ACK) | - SPHW_MSG_HEADER_SET(data_type, DATA_TYPE) | - SPHW_MSG_HEADER_SET(SEQ_ID_START_VAL, SEQID) | - SPHW_MSG_HEADER_SET(NOT_LAST_SEGMENT, LAST) | - SPHW_MSG_HEADER_SET(direction, DIRECTION) | - SPHW_MSG_HEADER_SET(cmd, CMD) | - /* The vf's offset to it's associated pf */ - SPHW_MSG_HEADER_SET(msg_info->msg_id, MSG_ID) | - SPHW_MSG_HEADER_SET(rsp_aeq_id, AEQ_ID) | - SPHW_MSG_HEADER_SET(SPHW_MSG_FROM_MBOX, SOURCE) | - SPHW_MSG_HEADER_SET(!!msg_info->status, STATUS) | - SPHW_MSG_HEADER_SET(sphw_global_func_id(hwdev), SRC_GLB_FUNC_IDX); - - while (!(SPHW_MSG_HEADER_GET(header, LAST))) { - if (left <= MBOX_SEG_LEN) { - header &= ~MBOX_SEGLEN_MASK; - header |= SPHW_MSG_HEADER_SET(left, SEG_LEN); - header |= SPHW_MSG_HEADER_SET(LAST_SEGMENT, LAST); - - seg_len = left; - } - - err = send_mbox_seg(func_to_func, header, dst_func, msg_seg, - seg_len, msg_info); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to send mbox seg, seq_id=0x%llx\n", - SPHW_MSG_HEADER_GET(header, SEQID)); - goto send_err; - } - - left -= MBOX_SEG_LEN; - msg_seg += MBOX_SEG_LEN; - - seq_id++; - header &= ~(SPHW_MSG_HEADER_SET(SPHW_MSG_HEADER_SEQID_MASK, SEQID)); - header |= SPHW_MSG_HEADER_SET(seq_id, SEQID); - } - -send_err: - mutex_unlock(&func_to_func->msg_send_lock); - - return err; -} - -static void set_mbox_to_func_event(struct sphw_mbox *func_to_func, - enum mbox_event_state event_flag) -{ - spin_lock(&func_to_func->mbox_lock); - func_to_func->event_flag = event_flag; - spin_unlock(&func_to_func->mbox_lock); -} - -static enum sphw_wait_return check_mbox_msg_finish(void *priv_data) -{ - struct sphw_mbox *func_to_func = priv_data; - - if (MBOX_MSG_CHANNEL_STOP(func_to_func)) - return WAIT_PROCESS_ERR; - - return (func_to_func->event_flag == EVENT_SUCCESS) ? - WAIT_PROCESS_CPL : WAIT_PROCESS_WAITING; -} - -static int wait_mbox_msg_completion(struct sphw_mbox *func_to_func, - u32 timeout) -{ - int err; - - timeout = timeout ? timeout : SPHW_MBOX_COMP_TIME; - err = sphw_wait_for_timeout(func_to_func, check_mbox_msg_finish, - timeout, USEC_PER_MSEC); - if (err) { - set_mbox_to_func_event(func_to_func, EVENT_TIMEOUT); - return -ETIMEDOUT; - } - - set_mbox_to_func_event(func_to_func, EVENT_END); - - return 0; -} - -#define TRY_MBOX_LOCK_SLEPP 1000 -static int send_mbox_msg_lock(struct sphw_mbox *func_to_func, u16 channel) -{ - if (!func_to_func->lock_channel_en) { - mutex_lock(&func_to_func->mbox_send_lock); - return 0; - } - - while (!test_bit(channel, &func_to_func->channel_stop)) { - if (mutex_trylock(&func_to_func->mbox_send_lock)) - return 0; - - usleep_range(TRY_MBOX_LOCK_SLEPP - 1, TRY_MBOX_LOCK_SLEPP); - } - - return -EAGAIN; -} - -static void send_mbox_msg_unlock(struct sphw_mbox *func_to_func) -{ - mutex_unlock(&func_to_func->mbox_send_lock); -} - -int sphw_mbox_to_func(struct sphw_mbox *func_to_func, u8 mod, u16 cmd, u16 dst_func, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, u32 timeout, u16 channel) -{ - /* use mbox_resp to hole data which responsed from other function */ - struct sphw_msg_desc *msg_desc = NULL; - struct mbox_msg_info msg_info = {0}; - int err; - - if (!func_to_func->hwdev->chip_present_flag) - return -EPERM; - - /* expect response message */ - msg_desc = get_mbox_msg_desc(func_to_func, SPHW_MSG_RESPONSE, - dst_func); - if (!msg_desc) - return -EFAULT; - - err = send_mbox_msg_lock(func_to_func, channel); - if (err) - return err; - - func_to_func->cur_msg_channel = channel; - msg_info.msg_id = MBOX_MSG_ID_INC(func_to_func); - - set_mbox_to_func_event(func_to_func, EVENT_START); - - err = send_mbox_msg(func_to_func, mod, cmd, buf_in, in_size, dst_func, - SPHW_MSG_DIRECT_SEND, SPHW_MSG_ACK, &msg_info); - if (err) { - sdk_err(func_to_func->hwdev->dev_hdl, "Send mailbox mod %u, cmd %u failed, msg_id: %u, err: %d\n", - mod, cmd, msg_info.msg_id, err); - set_mbox_to_func_event(func_to_func, EVENT_FAIL); - goto send_err; - } - - if (wait_mbox_msg_completion(func_to_func, timeout)) { - sdk_err(func_to_func->hwdev->dev_hdl, - "Send mbox msg timeout, msg_id: %u\n", msg_info.msg_id); - sphw_dump_aeq_info(func_to_func->hwdev); - err = -ETIMEDOUT; - goto send_err; - } - - if (mod != msg_desc->mod || cmd != msg_desc->cmd) { - sdk_err(func_to_func->hwdev->dev_hdl, - "Invalid response mbox message, mod: 0x%x, cmd: 0x%x, expect mod: 0x%x, cmd: 0x%x\n", - msg_desc->mod, msg_desc->cmd, mod, cmd); - err = -EFAULT; - goto send_err; - } - - if (msg_desc->msg_info.status) { - err = msg_desc->msg_info.status; - goto send_err; - } - - if (buf_out && out_size) { - if (*out_size < msg_desc->msg_len) { - sdk_err(func_to_func->hwdev->dev_hdl, - "Invalid response mbox message length: %u for mod %d cmd %u, should less than: %u\n", - msg_desc->msg_len, mod, cmd, *out_size); - err = -EFAULT; - goto send_err; - } - - if (msg_desc->msg_len) - memcpy(buf_out, msg_desc->msg, msg_desc->msg_len); - - *out_size = msg_desc->msg_len; - } - -send_err: - send_mbox_msg_unlock(func_to_func); - - return err; -} - -static int mbox_func_params_valid(struct sphw_mbox *func_to_func, - void *buf_in, u16 in_size, u16 channel) -{ - if (!buf_in || !in_size) - return -EINVAL; - - if (in_size > SPHW_MBOX_DATA_SIZE) { - sdk_err(func_to_func->hwdev->dev_hdl, - "Mbox msg len %u exceed limit: [1, %u]\n", - in_size, SPHW_MBOX_DATA_SIZE); - return -EINVAL; - } - - if (channel >= SPHW_CHANNEL_MAX) { - sdk_err(func_to_func->hwdev->dev_hdl, - "Invalid channel id: 0x%x\n", channel); - return -EINVAL; - } - - return 0; -} - -int sphw_mbox_to_func_no_ack(struct sphw_hwdev *hwdev, u16 func_idx, u8 mod, u16 cmd, - void *buf_in, u16 in_size, u16 channel) -{ - struct mbox_msg_info msg_info = {0}; - int err = mbox_func_params_valid(hwdev->func_to_func, buf_in, in_size, - channel); - - if (err) - return err; - - err = send_mbox_msg_lock(hwdev->func_to_func, channel); - if (err) - return err; - - err = send_mbox_msg(hwdev->func_to_func, mod, cmd, buf_in, in_size, - func_idx, SPHW_MSG_DIRECT_SEND, - SPHW_MSG_NO_ACK, &msg_info); - if (err) - sdk_err(hwdev->dev_hdl, "Send mailbox no ack failed\n"); - - send_mbox_msg_unlock(hwdev->func_to_func); - - return err; -} - -int sphw_send_mbox_to_mgmt(struct sphw_hwdev *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u32 timeout, u16 channel) -{ - struct sphw_mbox *func_to_func = hwdev->func_to_func; - int err = mbox_func_params_valid(func_to_func, buf_in, in_size, channel); - - if (err) - return err; - - return sphw_mbox_to_func(func_to_func, mod, cmd, SPHW_MGMT_SRC_ID, - buf_in, in_size, buf_out, out_size, timeout, channel); -} - -void sphw_response_mbox_to_mgmt(struct sphw_hwdev *hwdev, u8 mod, u16 cmd, - void *buf_in, u16 in_size, u16 msg_id) -{ - struct mbox_msg_info msg_info; - - msg_info.msg_id = (u8)msg_id; - msg_info.status = 0; - - send_mbox_msg(hwdev->func_to_func, mod, cmd, buf_in, in_size, - SPHW_MGMT_SRC_ID, SPHW_MSG_RESPONSE, - SPHW_MSG_NO_ACK, &msg_info); -} - -int sphw_send_mbox_to_mgmt_no_ack(struct sphw_hwdev *hwdev, u8 mod, u16 cmd, - void *buf_in, u16 in_size, u16 channel) -{ - struct sphw_mbox *func_to_func = hwdev->func_to_func; - int err = mbox_func_params_valid(func_to_func, buf_in, in_size, - channel); - - if (err) - return err; - - return sphw_mbox_to_func_no_ack(hwdev, SPHW_MGMT_SRC_ID, mod, cmd, - buf_in, in_size, channel); -} - -int sphw_mbox_ppf_to_host(void *hwdev, u8 mod, u16 cmd, u8 host_id, - void *buf_in, u16 in_size, void *buf_out, - u16 *out_size, u32 timeout, u16 channel) -{ - struct sphw_hwdev *dev = hwdev; - u16 dst_ppf_func; - int err; - - if (!hwdev) - return -EINVAL; - - if (!(dev->chip_present_flag)) - return -EPERM; - - err = mbox_func_params_valid(dev->func_to_func, buf_in, in_size, - channel); - if (err) - return err; - - if (!SPHW_IS_PPF(dev)) { - sdk_err(dev->dev_hdl, "Params error, only ppf support send mbox to ppf. func_type: %d\n", - sphw_func_type(dev)); - return -EINVAL; - } - - if (host_id >= SPHW_MAX_HOST_NUM(dev) || - host_id == SPHW_PCI_INTF_IDX(dev->hwif)) { - sdk_err(dev->dev_hdl, "Params error, host id: %u\n", host_id); - return -EINVAL; - } - - dst_ppf_func = sphw_host_ppf_idx(dev, host_id); - if (dst_ppf_func >= SPHW_MAX_PF_NUM(dev)) { - sdk_err(dev->dev_hdl, "Dest host(%u) have not elect ppf(0x%x).\n", - host_id, dst_ppf_func); - return -EINVAL; - } - - return sphw_mbox_to_func(dev->func_to_func, mod, cmd, dst_ppf_func, buf_in, in_size, - buf_out, out_size, timeout, channel); -} - -int sphw_mbox_to_pf(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, void *buf_out, - u16 *out_size, u32 timeout, u16 channel) -{ - struct sphw_hwdev *dev = hwdev; - int err; - - if (!hwdev) - return -EINVAL; - - if (!(dev->chip_present_flag)) - return -EPERM; - - err = mbox_func_params_valid(dev->func_to_func, buf_in, in_size, - channel); - if (err) - return err; - - if (!SPHW_IS_VF(dev)) { - sdk_err(dev->dev_hdl, "Params error, func_type: %d\n", - sphw_func_type(dev)); - return -EINVAL; - } - - return sphw_mbox_to_func(dev->func_to_func, mod, cmd, sphw_pf_id_of_vf(dev), buf_in, - in_size, buf_out, out_size, timeout, channel); -} - -int sphw_mbox_to_vf(void *hwdev, u16 vf_id, u8 mod, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u32 timeout, u16 channel) -{ - struct sphw_mbox *func_to_func = NULL; - int err = 0; - u16 dst_func_idx; - - if (!hwdev) - return -EINVAL; - - func_to_func = ((struct sphw_hwdev *)hwdev)->func_to_func; - err = mbox_func_params_valid(func_to_func, buf_in, in_size, channel); - if (err) - return err; - - if (SPHW_IS_VF((struct sphw_hwdev *)hwdev)) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, "Params error, func_type: %d\n", - sphw_func_type(hwdev)); - return -EINVAL; - } - - if (!vf_id) { - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "VF id(%u) error!\n", vf_id); - return -EINVAL; - } - - /* vf_offset_to_pf + vf_id is the vf's global function id of vf in - * this pf - */ - dst_func_idx = sphw_glb_pf_vf_offset(hwdev) + vf_id; - - return sphw_mbox_to_func(func_to_func, mod, cmd, dst_func_idx, buf_in, - in_size, buf_out, out_size, timeout, channel); -} - -void sphw_mbox_enable_channel_lock(struct sphw_hwdev *hwdev, bool enable) -{ - hwdev->func_to_func->lock_channel_en = enable; - - sdk_info(hwdev->dev_hdl, "%s mbox channel lock\n", - enable ? "Enable" : "Disable"); -} - -static int alloc_mbox_msg_channel(struct sphw_msg_channel *msg_ch) -{ - msg_ch->resp_msg.msg = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL); - if (!msg_ch->resp_msg.msg) - return -ENOMEM; - - msg_ch->recv_msg.msg = kzalloc(MBOX_MAX_BUF_SZ, GFP_KERNEL); - if (!msg_ch->recv_msg.msg) { - kfree(msg_ch->resp_msg.msg); - return -ENOMEM; - } - - msg_ch->resp_msg.seq_id = SEQ_ID_MAX_VAL; - msg_ch->recv_msg.seq_id = SEQ_ID_MAX_VAL; - atomic_set(&msg_ch->recv_msg_cnt, 0); - - return 0; -} - -static void free_mbox_msg_channel(struct sphw_msg_channel *msg_ch) -{ - kfree(msg_ch->recv_msg.msg); - kfree(msg_ch->resp_msg.msg); -} - -static int init_mgmt_msg_channel(struct sphw_mbox *func_to_func) -{ - int err; - - err = alloc_mbox_msg_channel(&func_to_func->mgmt_msg); - if (err) { - sdk_err(func_to_func->hwdev->dev_hdl, "Failed to alloc mgmt message channel\n"); - return err; - } - - err = sphw_init_mbox_dma_queue(func_to_func); - if (err) { - sdk_err(func_to_func->hwdev->dev_hdl, "Failed to init mbox dma queue\n"); - free_mbox_msg_channel(&func_to_func->mgmt_msg); - } - - return err; -} - -static void deinit_mgmt_msg_channel(struct sphw_mbox *func_to_func) -{ - sphw_deinit_mbox_dma_queue(func_to_func); - free_mbox_msg_channel(&func_to_func->mgmt_msg); -} - -int sphw_mbox_init_host_msg_channel(struct sphw_hwdev *hwdev) -{ - struct sphw_mbox *func_to_func = hwdev->func_to_func; - u8 host_num = SPHW_MAX_HOST_NUM(hwdev); - int i, host_id, err; - - if (host_num == 0) - return 0; - - func_to_func->host_msg = kcalloc(host_num, - sizeof(*func_to_func->host_msg), - GFP_KERNEL); - if (!func_to_func->host_msg) { - sdk_err(func_to_func->hwdev->dev_hdl, "Failed to alloc host message array\n"); - return -ENOMEM; - } - - for (host_id = 0; host_id < host_num; host_id++) { - err = alloc_mbox_msg_channel(&func_to_func->host_msg[host_id]); - if (err) { - sdk_err(func_to_func->hwdev->dev_hdl, - "Failed to alloc host %d message channel\n", - host_id); - goto alloc_msg_ch_err; - } - } - - func_to_func->support_h2h_msg = true; - - return 0; - -alloc_msg_ch_err: - for (i = 0; i < host_id; i++) - free_mbox_msg_channel(&func_to_func->host_msg[i]); - - kfree(func_to_func->host_msg); - func_to_func->host_msg = NULL; - - return -ENOMEM; -} - -static void deinit_host_msg_channel(struct sphw_mbox *func_to_func) -{ - int i; - - if (!func_to_func->host_msg) - return; - - for (i = 0; i < SPHW_MAX_HOST_NUM(func_to_func->hwdev); i++) - free_mbox_msg_channel(&func_to_func->host_msg[i]); - - kfree(func_to_func->host_msg); - func_to_func->host_msg = NULL; -} - -int sphw_init_func_mbox_msg_channel(void *hwdev, u16 num_func) -{ - struct sphw_hwdev *dev = hwdev; - struct sphw_mbox *func_to_func = NULL; - u16 func_id, i; - int err; - - if (!hwdev || !num_func || num_func > SPHW_MAX_FUNCTIONS) - return -EINVAL; - - func_to_func = dev->func_to_func; - if (func_to_func->func_msg) - return (func_to_func->num_func_msg == num_func) ? 0 : -EFAULT; - - func_to_func->func_msg = - kcalloc(num_func, sizeof(*func_to_func->func_msg), GFP_KERNEL); - if (!func_to_func->func_msg) { - sdk_err(func_to_func->hwdev->dev_hdl, "Failed to alloc func message array\n"); - return -ENOMEM; - } - - for (func_id = 0; func_id < num_func; func_id++) { - err = alloc_mbox_msg_channel(&func_to_func->func_msg[func_id]); - if (err) { - sdk_err(func_to_func->hwdev->dev_hdl, - "Failed to alloc func %hu message channel\n", - func_id); - goto alloc_msg_ch_err; - } - } - - func_to_func->num_func_msg = num_func; - - return 0; - -alloc_msg_ch_err: - for (i = 0; i < func_id; i++) - free_mbox_msg_channel(&func_to_func->func_msg[i]); - - kfree(func_to_func->func_msg); - func_to_func->func_msg = NULL; - - return -ENOMEM; -} - -void sphw_deinit_func_mbox_msg_channel(struct sphw_hwdev *hwdev) -{ - struct sphw_mbox *func_to_func = hwdev->func_to_func; - u16 i; - - if (!func_to_func->func_msg) - return; - - for (i = 0; i < func_to_func->num_func_msg; i++) - free_mbox_msg_channel(&func_to_func->func_msg[i]); - - kfree(func_to_func->func_msg); - func_to_func->func_msg = NULL; -} - -struct sphw_msg_desc *get_mbox_msg_desc(struct sphw_mbox *func_to_func, u64 dir, u64 src_func_id) -{ - struct sphw_hwdev *hwdev = func_to_func->hwdev; - struct sphw_msg_channel *msg_ch = NULL; - u16 id; - - if (src_func_id == SPHW_MGMT_SRC_ID) { - msg_ch = &func_to_func->mgmt_msg; - } else if (SPHW_IS_VF(hwdev)) { - /* message from pf */ - msg_ch = func_to_func->func_msg; - if (src_func_id != sphw_pf_id_of_vf(hwdev) || !msg_ch) - return NULL; - } else if (src_func_id > sphw_glb_pf_vf_offset(hwdev)) { - /* message from vf */ - id = (u16)(src_func_id - 1U) - sphw_glb_pf_vf_offset(hwdev); - if (id >= func_to_func->num_func_msg) - return NULL; - - msg_ch = &func_to_func->func_msg[id]; - } else { - /* message from other host's ppf */ - if (!func_to_func->support_h2h_msg) - return NULL; - - for (id = 0; id < SPHW_MAX_HOST_NUM(hwdev); id++) { - if (src_func_id == sphw_host_ppf_idx(hwdev, (u8)id)) - break; - } - - if (id == SPHW_MAX_HOST_NUM(hwdev) || !func_to_func->host_msg) - return NULL; - - msg_ch = &func_to_func->host_msg[id]; - } - - return (dir == SPHW_MSG_DIRECT_SEND) ? - &msg_ch->recv_msg : &msg_ch->resp_msg; -} - -static void prepare_send_mbox(struct sphw_mbox *func_to_func) -{ - struct sphw_send_mbox *send_mbox = &func_to_func->send_mbox; - - send_mbox->data = MBOX_AREA(func_to_func->hwdev->hwif); -} - -static int alloc_mbox_wb_status(struct sphw_mbox *func_to_func) -{ - struct sphw_send_mbox *send_mbox = &func_to_func->send_mbox; - struct sphw_hwdev *hwdev = func_to_func->hwdev; - u32 addr_h, addr_l; - - send_mbox->wb_vaddr = dma_alloc_coherent(hwdev->dev_hdl, MBOX_WB_STATUS_LEN, - &send_mbox->wb_paddr, GFP_KERNEL); - if (!send_mbox->wb_vaddr) - return -ENOMEM; - - send_mbox->wb_status = send_mbox->wb_vaddr; - - addr_h = upper_32_bits(send_mbox->wb_paddr); - addr_l = lower_32_bits(send_mbox->wb_paddr); - - sphw_hwif_write_reg(hwdev->hwif, SPHW_FUNC_CSR_MAILBOX_RESULT_H_OFF, addr_h); - sphw_hwif_write_reg(hwdev->hwif, SPHW_FUNC_CSR_MAILBOX_RESULT_L_OFF, addr_l); - - return 0; -} - -static void free_mbox_wb_status(struct sphw_mbox *func_to_func) -{ - struct sphw_send_mbox *send_mbox = &func_to_func->send_mbox; - struct sphw_hwdev *hwdev = func_to_func->hwdev; - - sphw_hwif_write_reg(hwdev->hwif, SPHW_FUNC_CSR_MAILBOX_RESULT_H_OFF, 0); - sphw_hwif_write_reg(hwdev->hwif, SPHW_FUNC_CSR_MAILBOX_RESULT_L_OFF, 0); - - dma_free_coherent(hwdev->dev_hdl, MBOX_WB_STATUS_LEN, - send_mbox->wb_vaddr, send_mbox->wb_paddr); -} - -int sphw_func_to_func_init(struct sphw_hwdev *hwdev) -{ - struct sphw_mbox *func_to_func; - int err; - - func_to_func = kzalloc(sizeof(*func_to_func), GFP_KERNEL); - if (!func_to_func) - return -ENOMEM; - - hwdev->func_to_func = func_to_func; - func_to_func->hwdev = hwdev; - mutex_init(&func_to_func->mbox_send_lock); - mutex_init(&func_to_func->msg_send_lock); - spin_lock_init(&func_to_func->mbox_lock); - func_to_func->workq = - create_singlethread_workqueue(SPHW_MBOX_WQ_NAME); - if (!func_to_func->workq) { - sdk_err(hwdev->dev_hdl, "Failed to initialize MBOX workqueue\n"); - err = -ENOMEM; - goto create_mbox_workq_err; - } - - err = init_mgmt_msg_channel(func_to_func); - if (err) - goto init_mgmt_msg_ch_err; - - if (SPHW_IS_VF(hwdev)) { - /* VF to PF mbox message channel */ - err = sphw_init_func_mbox_msg_channel(hwdev, 1); - if (err) - goto init_func_msg_ch_err; - } - - err = alloc_mbox_wb_status(func_to_func); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to alloc mbox write back status\n"); - goto alloc_wb_status_err; - } - - prepare_send_mbox(func_to_func); - - return 0; - -alloc_wb_status_err: - if (SPHW_IS_VF(hwdev)) - sphw_deinit_func_mbox_msg_channel(hwdev); - -init_func_msg_ch_err: - deinit_mgmt_msg_channel(func_to_func); - -init_mgmt_msg_ch_err: - destroy_workqueue(func_to_func->workq); - -create_mbox_workq_err: - kfree(func_to_func); - - return err; -} - -void sphw_func_to_func_free(struct sphw_hwdev *hwdev) -{ - struct sphw_mbox *func_to_func = hwdev->func_to_func; - - /* destroy workqueue before free related mbox resources in case of - * illegal resource access - */ - destroy_workqueue(func_to_func->workq); - - free_mbox_wb_status(func_to_func); - if (SPHW_IS_PPF(hwdev)) - deinit_host_msg_channel(func_to_func); - sphw_deinit_func_mbox_msg_channel(hwdev); - deinit_mgmt_msg_channel(func_to_func); - - kfree(func_to_func); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mbox.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mbox.h deleted file mode 100644 index 9aebee1c088a..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mbox.h +++ /dev/null @@ -1,271 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_MBOX_H -#define SPHW_MBOX_H - -#include "sphw_crm.h" - -#define SPHW_MBOX_PF_SEND_ERR 0x1 - -#define SPHW_MGMT_SRC_ID 0x1FFF -#define SPHW_MAX_FUNCTIONS 4096 - -/* message header define */ -#define SPHW_MSG_HEADER_SRC_GLB_FUNC_IDX_SHIFT 0 -#define SPHW_MSG_HEADER_STATUS_SHIFT 13 -#define SPHW_MSG_HEADER_SOURCE_SHIFT 15 -#define SPHW_MSG_HEADER_AEQ_ID_SHIFT 16 -#define SPHW_MSG_HEADER_MSG_ID_SHIFT 18 -#define SPHW_MSG_HEADER_CMD_SHIFT 22 - -#define SPHW_MSG_HEADER_MSG_LEN_SHIFT 32 -#define SPHW_MSG_HEADER_MODULE_SHIFT 43 -#define SPHW_MSG_HEADER_SEG_LEN_SHIFT 48 -#define SPHW_MSG_HEADER_NO_ACK_SHIFT 54 -#define SPHW_MSG_HEADER_DATA_TYPE_SHIFT 55 -#define SPHW_MSG_HEADER_SEQID_SHIFT 56 -#define SPHW_MSG_HEADER_LAST_SHIFT 62 -#define SPHW_MSG_HEADER_DIRECTION_SHIFT 63 - -#define SPHW_MSG_HEADER_SRC_GLB_FUNC_IDX_MASK 0x1FFF -#define SPHW_MSG_HEADER_STATUS_MASK 0x1 -#define SPHW_MSG_HEADER_SOURCE_MASK 0x1 -#define SPHW_MSG_HEADER_AEQ_ID_MASK 0x3 -#define SPHW_MSG_HEADER_MSG_ID_MASK 0xF -#define SPHW_MSG_HEADER_CMD_MASK 0x3FF - -#define SPHW_MSG_HEADER_MSG_LEN_MASK 0x7FF -#define SPHW_MSG_HEADER_MODULE_MASK 0x1F -#define SPHW_MSG_HEADER_SEG_LEN_MASK 0x3F -#define SPHW_MSG_HEADER_NO_ACK_MASK 0x1 -#define SPHW_MSG_HEADER_DATA_TYPE_MASK 0x1 -#define SPHW_MSG_HEADER_SEQID_MASK 0x3F -#define SPHW_MSG_HEADER_LAST_MASK 0x1 -#define SPHW_MSG_HEADER_DIRECTION_MASK 0x1 - -#define SPHW_MSG_HEADER_GET(val, field) \ - (((val) >> SPHW_MSG_HEADER_##field##_SHIFT) & \ - SPHW_MSG_HEADER_##field##_MASK) -#define SPHW_MSG_HEADER_SET(val, field) \ - ((u64)(((u64)(val)) & SPHW_MSG_HEADER_##field##_MASK) << \ - SPHW_MSG_HEADER_##field##_SHIFT) - -#define IS_DMA_MBX_MSG(dst_func) ((dst_func) == SPHW_MGMT_SRC_ID) - -enum sphw_msg_direction_type { - SPHW_MSG_DIRECT_SEND = 0, - SPHW_MSG_RESPONSE = 1, -}; - -enum sphw_msg_segment_type { - NOT_LAST_SEGMENT = 0, - LAST_SEGMENT = 1, -}; - -enum sphw_msg_ack_type { - SPHW_MSG_ACK, - SPHW_MSG_NO_ACK, -}; - -enum sphw_data_type { - SPHW_DATA_INLINE = 0, - SPHW_DATA_DMA = 1, -}; - -enum sphw_msg_src_type { - SPHW_MSG_FROM_MGMT = 0, - SPHW_MSG_FROM_MBOX = 1, -}; - -enum sphw_msg_aeq_type { - SPHW_ASYNC_MSG_AEQ = 0, - /* indicate dest func or mgmt cpu which aeq to response mbox message */ - SPHW_MBOX_RSP_MSG_AEQ = 1, - /* indicate mgmt cpu which aeq to response api cmd message */ - SPHW_MGMT_RSP_MSG_AEQ = 2, -}; - -#define SPHW_MBOX_WQ_NAME "sphw_mbox" - -enum sphw_mbox_seg_errcode { - MBOX_ERRCODE_NO_ERRORS = 0, - /* VF send the mailbox data to the wrong destination functions */ - MBOX_ERRCODE_VF_TO_WRONG_FUNC = 0x100, - /* PPF send the mailbox data to the wrong destination functions */ - MBOX_ERRCODE_PPF_TO_WRONG_FUNC = 0x200, - /* PF send the mailbox data to the wrong destination functions */ - MBOX_ERRCODE_PF_TO_WRONG_FUNC = 0x300, - /* The mailbox data size is set to all zero */ - MBOX_ERRCODE_ZERO_DATA_SIZE = 0x400, - /* The sender function attribute has not been learned by hardware */ - MBOX_ERRCODE_UNKNOWN_SRC_FUNC = 0x500, - /* The receiver function attr has not been learned by hardware */ - MBOX_ERRCODE_UNKNOWN_DES_FUNC = 0x600, -}; - -struct mbox_msg_info { - u8 msg_id; - u8 status; /* can only use 1 bit */ -}; - -struct sphw_msg_desc { - void *msg; - u16 msg_len; - u8 seq_id; - u8 mod; - u16 cmd; - struct mbox_msg_info msg_info; -}; - -struct sphw_msg_channel { - struct sphw_msg_desc resp_msg; - struct sphw_msg_desc recv_msg; - - atomic_t recv_msg_cnt; -}; - -/* Receive other functions mbox message */ -struct sphw_recv_mbox { - void *msg; - u16 msg_len; - u8 msg_id; - u8 mod; - u16 cmd; - u16 src_func_idx; - enum sphw_msg_ack_type ack_type; - void *resp_buff; -}; - -struct sphw_send_mbox { - u8 *data; - - u64 *wb_status; /* write back status */ - void *wb_vaddr; - dma_addr_t wb_paddr; -}; - -enum mbox_event_state { - EVENT_START = 0, - EVENT_FAIL, - EVENT_SUCCESS, - EVENT_TIMEOUT, - EVENT_END, -}; - -enum sphw_mbox_cb_state { - SPHW_VF_MBOX_CB_REG = 0, - SPHW_VF_MBOX_CB_RUNNING, - SPHW_PF_MBOX_CB_REG, - SPHW_PF_MBOX_CB_RUNNING, - SPHW_PPF_MBOX_CB_REG, - SPHW_PPF_MBOX_CB_RUNNING, - SPHW_PPF_TO_PF_MBOX_CB_REG, - SPHW_PPF_TO_PF_MBOX_CB_RUNNIG, -}; - -struct mbox_dma_msg { - u32 xor; - u32 dma_addr_high; - u32 dma_addr_low; - u32 msg_len; - u64 rsvd; -}; - -struct mbox_dma_queue { - void *dma_buff_vaddr; - dma_addr_t dma_buff_paddr; - - u16 depth; - u16 prod_idx; - u16 cons_idx; -}; - -struct sphw_mbox { - struct sphw_hwdev *hwdev; - - bool lock_channel_en; - unsigned long channel_stop; - u16 cur_msg_channel; - - /* lock for send mbox message and ack message */ - struct mutex mbox_send_lock; - /* lock for send mbox message */ - struct mutex msg_send_lock; - struct sphw_send_mbox send_mbox; - - struct mbox_dma_queue sync_msg_queue; - struct mbox_dma_queue async_msg_queue; - - struct workqueue_struct *workq; - - struct sphw_msg_channel mgmt_msg; /* driver and MGMT CPU */ - struct sphw_msg_channel *host_msg; /* PPF message between hosts */ - struct sphw_msg_channel *func_msg; /* PF to VF or VF to PF */ - u16 num_func_msg; - bool support_h2h_msg; /* host to host */ - - /* vf receive pf/ppf callback */ - sphw_vf_mbox_cb vf_mbox_cb[SPHW_MOD_MAX]; - void *vf_mbox_data[SPHW_MOD_MAX]; - /* pf/ppf receive vf callback */ - sphw_pf_mbox_cb pf_mbox_cb[SPHW_MOD_MAX]; - void *pf_mbox_data[SPHW_MOD_MAX]; - /* ppf receive pf/ppf callback */ - sphw_ppf_mbox_cb ppf_mbox_cb[SPHW_MOD_MAX]; - void *ppf_mbox_data[SPHW_MOD_MAX]; - /* pf receive ppf callback */ - sphw_pf_recv_from_ppf_mbox_cb pf_recv_ppf_mbox_cb[SPHW_MOD_MAX]; - void *pf_recv_ppf_mbox_data[SPHW_MOD_MAX]; - unsigned long ppf_to_pf_mbox_cb_state[SPHW_MOD_MAX]; - unsigned long ppf_mbox_cb_state[SPHW_MOD_MAX]; - unsigned long pf_mbox_cb_state[SPHW_MOD_MAX]; - unsigned long vf_mbox_cb_state[SPHW_MOD_MAX]; - - u8 send_msg_id; - enum mbox_event_state event_flag; - /* lock for mbox event flag */ - spinlock_t mbox_lock; -}; - -struct sphw_mbox_work { - struct work_struct work; - struct sphw_mbox *func_to_func; - struct sphw_recv_mbox *recv_mbox; - struct sphw_msg_channel *msg_ch; -}; - -struct vf_cmd_check_handle { - u16 cmd; - bool (*check_cmd)(struct sphw_hwdev *hwdev, u16 src_func_idx, - void *buf_in, u16 in_size); -}; - -void sphw_mbox_func_aeqe_handler(void *handle, u8 *header, u8 size); - -int sphw_func_to_func_init(struct sphw_hwdev *hwdev); - -void sphw_func_to_func_free(struct sphw_hwdev *hwdev); - -int sphw_send_mbox_to_mgmt(struct sphw_hwdev *hwdev, u8 mod, u16 cmd, - void *buf_in, u16 in_size, void *buf_out, - u16 *out_size, u32 timeout, u16 channel); - -void sphw_response_mbox_to_mgmt(struct sphw_hwdev *hwdev, u8 mod, u16 cmd, - void *buf_in, u16 in_size, u16 msg_id); - -int sphw_send_mbox_to_mgmt_no_ack(struct sphw_hwdev *hwdev, u8 mod, u16 cmd, - void *buf_in, u16 in_size, u16 channel); -int sphw_mbox_to_func(struct sphw_mbox *func_to_func, u8 mod, u16 cmd, - u16 dst_func, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u32 timeout, u16 channel); - -int sphw_mbox_ppf_to_host(void *hwdev, u8 mod, u16 cmd, u8 host_id, - void *buf_in, u16 in_size, void *buf_out, - u16 *out_size, u32 timeout, u16 channel); - -int sphw_mbox_init_host_msg_channel(struct sphw_hwdev *hwdev); - -void sphw_mbox_enable_channel_lock(struct sphw_hwdev *hwdev, bool enable); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt.c deleted file mode 100644 index a66f40635963..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt.c +++ /dev/null @@ -1,895 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/spinlock.h> -#include <linux/completion.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/semaphore.h> -#include <linux/delay.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_common.h" -#include "sphw_comm_cmd.h" -#include "sphw_hwdev.h" -#include "sphw_eqs.h" -#include "sphw_mbox.h" -#include "sphw_api_cmd.h" -#include "sphw_prof_adap.h" -#include "sphw_mgmt.h" -#include "sphw_csr.h" - -#define SPHW_MSG_TO_MGMT_MAX_LEN 2016 - -#define SPHW_API_CHAIN_AEQ_ID 2 -#define MAX_PF_MGMT_BUF_SIZE 2048UL -#define SEGMENT_LEN 48 -#define ASYNC_MSG_FLAG 0x8 -#define MGMT_MSG_MAX_SEQ_ID (ALIGN(SPHW_MSG_TO_MGMT_MAX_LEN, \ - SEGMENT_LEN) / SEGMENT_LEN) - -#define BUF_OUT_DEFAULT_SIZE 1 - -#define MGMT_MSG_SIZE_MIN 20 -#define MGMT_MSG_SIZE_STEP 16 -#define MGMT_MSG_RSVD_FOR_DEV 8 - -#define SYNC_MSG_ID_MASK 0x7 -#define ASYNC_MSG_ID_MASK 0x7 - -#define SYNC_FLAG 0 -#define ASYNC_FLAG 1 - -#define MSG_NO_RESP 0xFFFF - -#define MGMT_MSG_TIMEOUT 20000 /* millisecond */ - -#define SYNC_MSG_ID(pf_to_mgmt) ((pf_to_mgmt)->sync_msg_id) - -#define SYNC_MSG_ID_INC(pf_to_mgmt) (SYNC_MSG_ID(pf_to_mgmt) = \ - (SYNC_MSG_ID(pf_to_mgmt) + 1) & SYNC_MSG_ID_MASK) -#define ASYNC_MSG_ID(pf_to_mgmt) ((pf_to_mgmt)->async_msg_id) - -#define ASYNC_MSG_ID_INC(pf_to_mgmt) (ASYNC_MSG_ID(pf_to_mgmt) = \ - ((ASYNC_MSG_ID(pf_to_mgmt) + 1) & ASYNC_MSG_ID_MASK) | ASYNC_MSG_FLAG) - -static void pf_to_mgmt_send_event_set(struct sphw_msg_pf_to_mgmt *pf_to_mgmt, - int event_flag) -{ - spin_lock(&pf_to_mgmt->sync_event_lock); - pf_to_mgmt->event_flag = event_flag; - spin_unlock(&pf_to_mgmt->sync_event_lock); -} - -/** - * sphw_register_mgmt_msg_cb - register sync msg handler for a module - * @hwdev: the pointer to hw device - * @mod: module in the chip that this handler will handle its sync messages - * @pri_handle: specific mod's private data that will be used in callback - * @callback: the handler for a sync message that will handle messages - **/ -int sphw_register_mgmt_msg_cb(void *hwdev, u8 mod, void *pri_handle, sphw_mgmt_msg_cb callback) -{ - struct sphw_msg_pf_to_mgmt *pf_to_mgmt = NULL; - - if (mod >= SPHW_MOD_HW_MAX || !hwdev) - return -EFAULT; - - pf_to_mgmt = ((struct sphw_hwdev *)hwdev)->pf_to_mgmt; - if (!pf_to_mgmt) - return -EINVAL; - - pf_to_mgmt->recv_mgmt_msg_cb[mod] = callback; - pf_to_mgmt->recv_mgmt_msg_data[mod] = pri_handle; - - set_bit(SPHW_MGMT_MSG_CB_REG, &pf_to_mgmt->mgmt_msg_cb_state[mod]); - - return 0; -} - -/** - * sphw_unregister_mgmt_msg_cb - unregister sync msg handler for a module - * @hwdev: the pointer to hw device - * @mod: module in the chip that this handler will handle its sync messages - **/ -void sphw_unregister_mgmt_msg_cb(void *hwdev, u8 mod) -{ - struct sphw_msg_pf_to_mgmt *pf_to_mgmt = NULL; - - if (!hwdev || mod >= SPHW_MOD_HW_MAX) - return; - - pf_to_mgmt = ((struct sphw_hwdev *)hwdev)->pf_to_mgmt; - if (!pf_to_mgmt) - return; - - clear_bit(SPHW_MGMT_MSG_CB_REG, &pf_to_mgmt->mgmt_msg_cb_state[mod]); - - while (test_bit(SPHW_MGMT_MSG_CB_RUNNING, &pf_to_mgmt->mgmt_msg_cb_state[mod])) - usleep_range(900, 1000); - - pf_to_mgmt->recv_mgmt_msg_cb[mod] = NULL; - pf_to_mgmt->recv_mgmt_msg_data[mod] = NULL; -} - -/** - * mgmt_msg_len - calculate the total message length - * @msg_data_len: the length of the message data - * Return: the total message length - **/ -static u16 mgmt_msg_len(u16 msg_data_len) -{ - /* u64 - the size of the header */ - u16 msg_size; - - msg_size = (u16)(MGMT_MSG_RSVD_FOR_DEV + sizeof(u64) + msg_data_len); - - if (msg_size > MGMT_MSG_SIZE_MIN) - msg_size = MGMT_MSG_SIZE_MIN + - ALIGN((msg_size - MGMT_MSG_SIZE_MIN), - MGMT_MSG_SIZE_STEP); - else - msg_size = MGMT_MSG_SIZE_MIN; - - return msg_size; -} - -/** - * prepare_header - prepare the header of the message - * @pf_to_mgmt: PF to MGMT channel - * @header: pointer of the header to prepare - * @msg_len: the length of the message - * @mod: module in the chip that will get the message - * @direction: the direction of the original message - * @msg_id: message id - **/ -static void prepare_header(struct sphw_msg_pf_to_mgmt *pf_to_mgmt, - u64 *header, u16 msg_len, u8 mod, - enum sphw_msg_ack_type ack_type, - enum sphw_msg_direction_type direction, - enum sphw_mgmt_cmd cmd, u32 msg_id) -{ - struct sphw_hwif *hwif = pf_to_mgmt->hwdev->hwif; - - *header = SPHW_MSG_HEADER_SET(msg_len, MSG_LEN) | - SPHW_MSG_HEADER_SET(mod, MODULE) | - SPHW_MSG_HEADER_SET(msg_len, SEG_LEN) | - SPHW_MSG_HEADER_SET(ack_type, NO_ACK) | - SPHW_MSG_HEADER_SET(SPHW_DATA_INLINE, DATA_TYPE) | - SPHW_MSG_HEADER_SET(0, SEQID) | - SPHW_MSG_HEADER_SET(SPHW_API_CHAIN_AEQ_ID, AEQ_ID) | - SPHW_MSG_HEADER_SET(LAST_SEGMENT, LAST) | - SPHW_MSG_HEADER_SET(direction, DIRECTION) | - SPHW_MSG_HEADER_SET(cmd, CMD) | - SPHW_MSG_HEADER_SET(SPHW_MSG_FROM_MGMT, SOURCE) | - SPHW_MSG_HEADER_SET(hwif->attr.func_global_idx, SRC_GLB_FUNC_IDX) | - SPHW_MSG_HEADER_SET(msg_id, MSG_ID); -} - -/** - * prepare_mgmt_cmd - prepare the mgmt command - * @mgmt_cmd: pointer to the command to prepare - * @header: pointer of the header to prepare - * @msg: the data of the message - * @msg_len: the length of the message - **/ -static void prepare_mgmt_cmd(u8 *mgmt_cmd, u64 *header, const void *msg, - int msg_len) -{ - memset(mgmt_cmd, 0, MGMT_MSG_RSVD_FOR_DEV); - - mgmt_cmd += MGMT_MSG_RSVD_FOR_DEV; - memcpy(mgmt_cmd, header, sizeof(*header)); - - mgmt_cmd += sizeof(*header); - memcpy(mgmt_cmd, msg, msg_len); -} - -/** - * send_msg_to_mgmt_sync - send async message - * @pf_to_mgmt: PF to MGMT channel - * @mod: module in the chip that will get the message - * @cmd: command of the message - * @msg: the msg data - * @msg_len: the msg data length - * @direction: the direction of the original message - * @resp_msg_id: msg id to response for - * Return: 0 - success, negative - failure - **/ -static int send_msg_to_mgmt_sync(struct sphw_msg_pf_to_mgmt *pf_to_mgmt, - u8 mod, u16 cmd, const void *msg, u16 msg_len, - enum sphw_msg_ack_type ack_type, - enum sphw_msg_direction_type direction, - u16 resp_msg_id) -{ - void *mgmt_cmd = pf_to_mgmt->sync_msg_buf; - struct sphw_api_cmd_chain *chain = NULL; - u8 node_id = SPHW_MGMT_CPU_NODE_ID(pf_to_mgmt->hwdev); - u64 header; - u16 cmd_size = mgmt_msg_len(msg_len); - - if (!sphw_get_chip_present_flag(pf_to_mgmt->hwdev)) - return -EFAULT; - - if (direction == SPHW_MSG_RESPONSE) - prepare_header(pf_to_mgmt, &header, msg_len, mod, ack_type, - direction, cmd, resp_msg_id); - else - prepare_header(pf_to_mgmt, &header, msg_len, mod, ack_type, - direction, cmd, SYNC_MSG_ID_INC(pf_to_mgmt)); - chain = pf_to_mgmt->cmd_chain[SPHW_API_CMD_WRITE_TO_MGMT_CPU]; - - if (ack_type == SPHW_MSG_ACK) - pf_to_mgmt_send_event_set(pf_to_mgmt, SEND_EVENT_START); - - prepare_mgmt_cmd((u8 *)mgmt_cmd, &header, msg, msg_len); - - return sphw_api_cmd_write(chain, node_id, mgmt_cmd, cmd_size); -} - -/** - * send_msg_to_mgmt_async - send async message - * @pf_to_mgmt: PF to MGMT channel - * @mod: module in the chip that will get the message - * @cmd: command of the message - * @msg: the data of the message - * @msg_len: the length of the message - * @direction: the direction of the original message - * Return: 0 - success, negative - failure - **/ -static int send_msg_to_mgmt_async(struct sphw_msg_pf_to_mgmt *pf_to_mgmt, - u8 mod, u16 cmd, const void *msg, u16 msg_len, - enum sphw_msg_direction_type direction) -{ - void *mgmt_cmd = pf_to_mgmt->async_msg_buf; - struct sphw_api_cmd_chain *chain = NULL; - u8 node_id = SPHW_MGMT_CPU_NODE_ID(pf_to_mgmt->hwdev); - u64 header; - u16 cmd_size = mgmt_msg_len(msg_len); - - if (!sphw_get_chip_present_flag(pf_to_mgmt->hwdev)) - return -EFAULT; - - prepare_header(pf_to_mgmt, &header, msg_len, mod, SPHW_MSG_NO_ACK, - direction, cmd, ASYNC_MSG_ID(pf_to_mgmt)); - - prepare_mgmt_cmd((u8 *)mgmt_cmd, &header, msg, msg_len); - - chain = pf_to_mgmt->cmd_chain[SPHW_API_CMD_WRITE_ASYNC_TO_MGMT_CPU]; - - return sphw_api_cmd_write(chain, node_id, mgmt_cmd, cmd_size); -} - -static inline void msg_to_mgmt_pre(u8 mod, void *buf_in) -{ - struct sphw_msg_head *msg_head = NULL; - - /* set aeq fix num to 3, need to ensure response aeq id < 3*/ - if (mod == SPHW_MOD_COMM || mod == SPHW_MOD_L2NIC) { - msg_head = buf_in; - - if (msg_head->resp_aeq_num >= SPHW_MAX_AEQS) - msg_head->resp_aeq_num = 0; - } -} - -int sphw_pf_to_mgmt_sync(void *hwdev, u8 mod, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, u32 timeout) -{ - struct sphw_msg_pf_to_mgmt *pf_to_mgmt = NULL; - void *dev = ((struct sphw_hwdev *)hwdev)->dev_hdl; - struct sphw_recv_msg *recv_msg = NULL; - struct completion *recv_done = NULL; - ulong timeo; - int err; - ulong ret; - - msg_to_mgmt_pre(mod, buf_in); - - pf_to_mgmt = ((struct sphw_hwdev *)hwdev)->pf_to_mgmt; - - /* Lock the sync_msg_buf */ - down(&pf_to_mgmt->sync_msg_lock); - recv_msg = &pf_to_mgmt->recv_resp_msg_from_mgmt; - recv_done = &recv_msg->recv_done; - - init_completion(recv_done); - - err = send_msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size, - SPHW_MSG_ACK, SPHW_MSG_DIRECT_SEND, - MSG_NO_RESP); - if (err) { - sdk_err(dev, "Failed to send sync msg to mgmt, sync_msg_id: %u\n", - pf_to_mgmt->sync_msg_id); - pf_to_mgmt_send_event_set(pf_to_mgmt, SEND_EVENT_FAIL); - goto unlock_sync_msg; - } - - timeo = msecs_to_jiffies(timeout ? timeout : MGMT_MSG_TIMEOUT); - - ret = wait_for_completion_timeout(recv_done, timeo); - if (!ret) { - sdk_err(dev, "Mgmt response sync cmd timeout, sync_msg_id: %u\n", - pf_to_mgmt->sync_msg_id); - sphw_dump_aeq_info((struct sphw_hwdev *)hwdev); - err = -ETIMEDOUT; - pf_to_mgmt_send_event_set(pf_to_mgmt, SEND_EVENT_TIMEOUT); - goto unlock_sync_msg; - } - pf_to_mgmt_send_event_set(pf_to_mgmt, SEND_EVENT_END); - - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) { - up(&pf_to_mgmt->sync_msg_lock); - return -ETIMEDOUT; - } - - if (buf_out && out_size) { - if (*out_size < recv_msg->msg_len) { - sdk_err(dev, "Invalid response message length: %u for mod %d cmd %u from mgmt, should less than: %u\n", - recv_msg->msg_len, mod, cmd, *out_size); - err = -EFAULT; - goto unlock_sync_msg; - } - - if (recv_msg->msg_len) - memcpy(buf_out, recv_msg->msg, recv_msg->msg_len); - - *out_size = recv_msg->msg_len; - } - -unlock_sync_msg: - up(&pf_to_mgmt->sync_msg_lock); - - return err; -} - -int sphw_pf_to_mgmt_async(void *hwdev, u8 mod, u16 cmd, const void *buf_in, u16 in_size) -{ - struct sphw_msg_pf_to_mgmt *pf_to_mgmt; - void *dev = ((struct sphw_hwdev *)hwdev)->dev_hdl; - int err; - - pf_to_mgmt = ((struct sphw_hwdev *)hwdev)->pf_to_mgmt; - - /* Lock the async_msg_buf */ - spin_lock_bh(&pf_to_mgmt->async_msg_lock); - ASYNC_MSG_ID_INC(pf_to_mgmt); - - err = send_msg_to_mgmt_async(pf_to_mgmt, mod, cmd, buf_in, in_size, - SPHW_MSG_DIRECT_SEND); - spin_unlock_bh(&pf_to_mgmt->async_msg_lock); - - if (err) { - sdk_err(dev, "Failed to send async mgmt msg\n"); - return err; - } - - return 0; -} - -int sphw_pf_msg_to_mgmt_sync(void *hwdev, u8 mod, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, u32 timeout) -{ - if (!hwdev) - return -EINVAL; - - if (!sphw_get_chip_present_flag(hwdev)) - return -EPERM; - - if (in_size > SPHW_MSG_TO_MGMT_MAX_LEN) - return -EINVAL; - - return sphw_pf_to_mgmt_sync(hwdev, mod, cmd, buf_in, in_size, buf_out, out_size, timeout); -} - -int sphw_msg_to_mgmt_sync(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, void *buf_out, - u16 *out_size, u32 timeout, u16 channel) -{ - if (!hwdev) - return -EINVAL; - - if (!sphw_get_chip_present_flag(hwdev)) - return -EPERM; - - return sphw_send_mbox_to_mgmt(hwdev, mod, cmd, buf_in, in_size, - buf_out, out_size, timeout, channel); -} - -int sphw_msg_to_mgmt_no_ack(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, u16 channel) -{ - if (!hwdev) - return -EINVAL; - - if (!sphw_get_chip_present_flag(hwdev)) - return -EPERM; - - return sphw_send_mbox_to_mgmt_no_ack(hwdev, mod, cmd, buf_in, in_size, channel); -} - -int sphw_msg_to_mgmt_async(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, u16 channel) -{ - return sphw_msg_to_mgmt_api_chain_async(hwdev, mod, cmd, buf_in, in_size); -} - -int sphw_msg_to_mgmt_api_chain_sync(void *hwdev, u8 mod, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u32 timeout) -{ - if (!hwdev) - return -EINVAL; - - if (!sphw_get_chip_present_flag(hwdev)) - return -EPERM; - - return sphw_pf_msg_to_mgmt_sync(hwdev, mod, cmd, buf_in, in_size, - buf_out, out_size, timeout); -} - -int sphw_msg_to_mgmt_api_chain_async(void *hwdev, u8 mod, u16 cmd, const void *buf_in, u16 in_size) -{ - int err; - - if (!hwdev) - return -EINVAL; - - if (sphw_func_type(hwdev) == TYPE_VF) { - err = -EFAULT; - sdk_err(((struct sphw_hwdev *)hwdev)->dev_hdl, - "VF don't support async cmd\n"); - } else { - err = sphw_pf_to_mgmt_async(hwdev, mod, cmd, buf_in, in_size); - } - - return err; -} - -static void send_mgmt_ack(struct sphw_msg_pf_to_mgmt *pf_to_mgmt, - u8 mod, u16 cmd, void *buf_in, u16 in_size, - u16 msg_id) -{ - u16 buf_size; - - if (!in_size) - buf_size = BUF_OUT_DEFAULT_SIZE; - else - buf_size = in_size; - - sphw_response_mbox_to_mgmt(pf_to_mgmt->hwdev, mod, cmd, buf_in, buf_size, msg_id); -} - -static void mgmt_recv_msg_handler(struct sphw_msg_pf_to_mgmt *pf_to_mgmt, - u8 mod, u16 cmd, void *buf_in, u16 in_size, - u16 msg_id, int need_resp) -{ - void *dev = pf_to_mgmt->hwdev->dev_hdl; - void *buf_out = pf_to_mgmt->mgmt_ack_buf; - enum sphw_mod_type tmp_mod = mod; - bool ack_first = false; - u16 out_size = 0; - - memset(buf_out, 0, MAX_PF_MGMT_BUF_SIZE); - - if (mod >= SPHW_MOD_HW_MAX) { - sdk_warn(dev, "Receive illegal message from mgmt cpu, mod = %d\n", - mod); - goto resp; - } - - set_bit(SPHW_MGMT_MSG_CB_RUNNING, &pf_to_mgmt->mgmt_msg_cb_state[tmp_mod]); - - if (!pf_to_mgmt->recv_mgmt_msg_cb[mod] || - !test_bit(SPHW_MGMT_MSG_CB_REG, - &pf_to_mgmt->mgmt_msg_cb_state[tmp_mod])) { - sdk_warn(dev, "Receive mgmt callback is null, mod = %d\n", - mod); - clear_bit(SPHW_MGMT_MSG_CB_RUNNING, &pf_to_mgmt->mgmt_msg_cb_state[tmp_mod]); - goto resp; - } - - pf_to_mgmt->recv_mgmt_msg_cb[tmp_mod](pf_to_mgmt->hwdev, - pf_to_mgmt->recv_mgmt_msg_data[tmp_mod], - cmd, buf_in, in_size, buf_out, &out_size); - - clear_bit(SPHW_MGMT_MSG_CB_RUNNING, &pf_to_mgmt->mgmt_msg_cb_state[tmp_mod]); - -resp: - if (!ack_first && need_resp) - send_mgmt_ack(pf_to_mgmt, mod, cmd, buf_out, out_size, msg_id); -} - -/** - * mgmt_resp_msg_handler - handler for response message from mgmt cpu - * @pf_to_mgmt: PF to MGMT channel - * @recv_msg: received message details - **/ -static void mgmt_resp_msg_handler(struct sphw_msg_pf_to_mgmt *pf_to_mgmt, - struct sphw_recv_msg *recv_msg) -{ - void *dev = pf_to_mgmt->hwdev->dev_hdl; - - /* delete async msg */ - if (recv_msg->msg_id & ASYNC_MSG_FLAG) - return; - - spin_lock(&pf_to_mgmt->sync_event_lock); - if (recv_msg->msg_id == pf_to_mgmt->sync_msg_id && - pf_to_mgmt->event_flag == SEND_EVENT_START) { - pf_to_mgmt->event_flag = SEND_EVENT_SUCCESS; - complete(&recv_msg->recv_done); - } else if (recv_msg->msg_id != pf_to_mgmt->sync_msg_id) { - sdk_err(dev, "Send msg id(0x%x) recv msg id(0x%x) dismatch, event state=%d\n", - pf_to_mgmt->sync_msg_id, recv_msg->msg_id, - pf_to_mgmt->event_flag); - } else { - sdk_err(dev, "Wait timeout, send msg id(0x%x) recv msg id(0x%x), event state=%d!\n", - pf_to_mgmt->sync_msg_id, recv_msg->msg_id, - pf_to_mgmt->event_flag); - } - spin_unlock(&pf_to_mgmt->sync_event_lock); -} - -static void recv_mgmt_msg_work_handler(struct work_struct *work) -{ - struct sphw_mgmt_msg_handle_work *mgmt_work = - container_of(work, struct sphw_mgmt_msg_handle_work, work); - - mgmt_recv_msg_handler(mgmt_work->pf_to_mgmt, mgmt_work->mod, - mgmt_work->cmd, mgmt_work->msg, - mgmt_work->msg_len, mgmt_work->msg_id, - !mgmt_work->async_mgmt_to_pf); - - kfree(mgmt_work->msg); - kfree(mgmt_work); -} - -static bool check_mgmt_seq_id_and_seg_len(struct sphw_recv_msg *recv_msg, - u8 seq_id, u8 seg_len) -{ - if (seq_id > MGMT_MSG_MAX_SEQ_ID || seg_len > SEGMENT_LEN) - return false; - - if (seq_id == 0) { - recv_msg->seq_id = seq_id; - } else { - if (seq_id != recv_msg->seq_id + 1) - return false; - - recv_msg->seq_id = seq_id; - } - - return true; -} - -/** - * recv_mgmt_msg_handler - handler a message from mgmt cpu - * @pf_to_mgmt: PF to MGMT channel - * @header: the header of the message - * @recv_msg: received message details - **/ -static void recv_mgmt_msg_handler(struct sphw_msg_pf_to_mgmt *pf_to_mgmt, - u8 *header, struct sphw_recv_msg *recv_msg) -{ - struct sphw_hwdev *hwdev = pf_to_mgmt->hwdev; - struct sphw_mgmt_msg_handle_work *mgmt_work = NULL; - u64 mbox_header = *((u64 *)header); - void *msg_body = header + sizeof(mbox_header); - u8 seq_id, seq_len; - u32 offset; - u64 dir; - - /* Don't need to get anything from hw when cmd is async */ - dir = SPHW_MSG_HEADER_GET(mbox_header, DIRECTION); - if (dir == SPHW_MSG_RESPONSE && SPHW_MSG_HEADER_GET(mbox_header, MSG_ID) & ASYNC_MSG_FLAG) - return; - - seq_len = SPHW_MSG_HEADER_GET(mbox_header, SEG_LEN); - seq_id = SPHW_MSG_HEADER_GET(mbox_header, SEQID); - - if (!check_mgmt_seq_id_and_seg_len(recv_msg, seq_id, seq_len)) { - sdk_err(hwdev->dev_hdl, - "Mgmt msg sequence id and segment length check fail, front seq_id: 0x%x,current seq_id: 0x%x, seg len: 0x%x\n", - recv_msg->seq_id, seq_id, seq_len); - /* set seq_id to invalid seq_id */ - recv_msg->seq_id = MGMT_MSG_MAX_SEQ_ID; - return; - } - - offset = seq_id * SEGMENT_LEN; - memcpy((u8 *)recv_msg->msg + offset, msg_body, seq_len); - - if (!SPHW_MSG_HEADER_GET(mbox_header, LAST)) - return; - - recv_msg->cmd = SPHW_MSG_HEADER_GET(mbox_header, CMD); - recv_msg->mod = SPHW_MSG_HEADER_GET(mbox_header, MODULE); - recv_msg->async_mgmt_to_pf = SPHW_MSG_HEADER_GET(mbox_header, NO_ACK); - recv_msg->msg_len = SPHW_MSG_HEADER_GET(mbox_header, MSG_LEN); - recv_msg->msg_id = SPHW_MSG_HEADER_GET(mbox_header, MSG_ID); - recv_msg->seq_id = MGMT_MSG_MAX_SEQ_ID; - - if (SPHW_MSG_HEADER_GET(mbox_header, DIRECTION) == SPHW_MSG_RESPONSE) { - mgmt_resp_msg_handler(pf_to_mgmt, recv_msg); - return; - } - - mgmt_work = kzalloc(sizeof(*mgmt_work), GFP_KERNEL); - if (!mgmt_work) { - sdk_err(hwdev->dev_hdl, "Allocate mgmt work memory failed\n"); - return; - } - - if (recv_msg->msg_len) { - mgmt_work->msg = kzalloc(recv_msg->msg_len, GFP_KERNEL); - if (!mgmt_work->msg) { - sdk_err(hwdev->dev_hdl, "Allocate mgmt msg memory failed\n"); - kfree(mgmt_work); - return; - } - } - - mgmt_work->pf_to_mgmt = pf_to_mgmt; - mgmt_work->msg_len = recv_msg->msg_len; - memcpy(mgmt_work->msg, recv_msg->msg, recv_msg->msg_len); - mgmt_work->msg_id = recv_msg->msg_id; - mgmt_work->mod = recv_msg->mod; - mgmt_work->cmd = recv_msg->cmd; - mgmt_work->async_mgmt_to_pf = recv_msg->async_mgmt_to_pf; - - INIT_WORK(&mgmt_work->work, recv_mgmt_msg_work_handler); - queue_work_on(sphw_get_work_cpu_affinity(hwdev, WORK_TYPE_MGMT_MSG), - pf_to_mgmt->workq, &mgmt_work->work); -} - -/** - * sphw_mgmt_msg_aeqe_handler - handler for a mgmt message event - * @handle: PF to MGMT channel - * @header: the header of the message - * @size: unused - **/ -void sphw_mgmt_msg_aeqe_handler(void *hwdev, u8 *header, u8 size) -{ - struct sphw_hwdev *dev = (struct sphw_hwdev *)hwdev; - struct sphw_msg_pf_to_mgmt *pf_to_mgmt = NULL; - struct sphw_recv_msg *recv_msg = NULL; - bool is_send_dir = false; - - if ((SPHW_MSG_HEADER_GET(*(u64 *)header, SOURCE) == - SPHW_MSG_FROM_MBOX)) { - sphw_mbox_func_aeqe_handler(hwdev, header, size); - return; - } - - pf_to_mgmt = dev->pf_to_mgmt; - if (!pf_to_mgmt) - return; - - is_send_dir = (SPHW_MSG_HEADER_GET(*(u64 *)header, DIRECTION) == - SPHW_MSG_DIRECT_SEND) ? true : false; - - recv_msg = is_send_dir ? &pf_to_mgmt->recv_msg_from_mgmt : - &pf_to_mgmt->recv_resp_msg_from_mgmt; - - recv_mgmt_msg_handler(pf_to_mgmt, header, recv_msg); -} - -/** - * alloc_recv_msg - allocate received message memory - * @recv_msg: pointer that will hold the allocated data - * Return: 0 - success, negative - failure - **/ -static int alloc_recv_msg(struct sphw_recv_msg *recv_msg) -{ - recv_msg->seq_id = MGMT_MSG_MAX_SEQ_ID; - - recv_msg->msg = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL); - if (!recv_msg->msg) - return -ENOMEM; - - return 0; -} - -/** - * free_recv_msg - free received message memory - * @recv_msg: pointer that holds the allocated data - **/ -static void free_recv_msg(struct sphw_recv_msg *recv_msg) -{ - kfree(recv_msg->msg); -} - -/** - * alloc_msg_buf - allocate all the message buffers of PF to MGMT channel - * @pf_to_mgmt: PF to MGMT channel - * Return: 0 - success, negative - failure - **/ -static int alloc_msg_buf(struct sphw_msg_pf_to_mgmt *pf_to_mgmt) -{ - int err; - void *dev = pf_to_mgmt->hwdev->dev_hdl; - - err = alloc_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt); - if (err) { - sdk_err(dev, "Failed to allocate recv msg\n"); - return err; - } - - err = alloc_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt); - if (err) { - sdk_err(dev, "Failed to allocate resp recv msg\n"); - goto alloc_msg_for_resp_err; - } - - pf_to_mgmt->async_msg_buf = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL); - if (!pf_to_mgmt->async_msg_buf) { - err = -ENOMEM; - goto async_msg_buf_err; - } - - pf_to_mgmt->sync_msg_buf = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL); - if (!pf_to_mgmt->sync_msg_buf) { - err = -ENOMEM; - goto sync_msg_buf_err; - } - - pf_to_mgmt->mgmt_ack_buf = kzalloc(MAX_PF_MGMT_BUF_SIZE, GFP_KERNEL); - if (!pf_to_mgmt->mgmt_ack_buf) { - err = -ENOMEM; - goto ack_msg_buf_err; - } - - return 0; - -ack_msg_buf_err: - kfree(pf_to_mgmt->sync_msg_buf); - -sync_msg_buf_err: - kfree(pf_to_mgmt->async_msg_buf); - -async_msg_buf_err: - free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt); - -alloc_msg_for_resp_err: - free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt); - return err; -} - -/** - * free_msg_buf - free all the message buffers of PF to MGMT channel - * @pf_to_mgmt: PF to MGMT channel - * Return: 0 - success, negative - failure - **/ -static void free_msg_buf(struct sphw_msg_pf_to_mgmt *pf_to_mgmt) -{ - kfree(pf_to_mgmt->mgmt_ack_buf); - kfree(pf_to_mgmt->sync_msg_buf); - kfree(pf_to_mgmt->async_msg_buf); - - free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt); - free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt); -} - -/** - * sphw_pf_to_mgmt_init - initialize PF to MGMT channel - * @hwdev: the pointer to hw device - * Return: 0 - success, negative - failure - **/ -int sphw_pf_to_mgmt_init(struct sphw_hwdev *hwdev) -{ - struct sphw_msg_pf_to_mgmt *pf_to_mgmt; - void *dev = hwdev->dev_hdl; - int err; - - pf_to_mgmt = kzalloc(sizeof(*pf_to_mgmt), GFP_KERNEL); - if (!pf_to_mgmt) - return -ENOMEM; - - hwdev->pf_to_mgmt = pf_to_mgmt; - pf_to_mgmt->hwdev = hwdev; - spin_lock_init(&pf_to_mgmt->async_msg_lock); - spin_lock_init(&pf_to_mgmt->sync_event_lock); - sema_init(&pf_to_mgmt->sync_msg_lock, 1); - pf_to_mgmt->workq = create_singlethread_workqueue(SPHW_MGMT_WQ_NAME); - if (!pf_to_mgmt->workq) { - sdk_err(dev, "Failed to initialize MGMT workqueue\n"); - err = -ENOMEM; - goto create_mgmt_workq_err; - } - - err = alloc_msg_buf(pf_to_mgmt); - if (err) { - sdk_err(dev, "Failed to allocate msg buffers\n"); - goto alloc_msg_buf_err; - } - - err = sphw_api_cmd_init(hwdev, pf_to_mgmt->cmd_chain); - if (err) { - sdk_err(dev, "Failed to init the api cmd chains\n"); - goto api_cmd_init_err; - } - - return 0; - -api_cmd_init_err: - free_msg_buf(pf_to_mgmt); - -alloc_msg_buf_err: - destroy_workqueue(pf_to_mgmt->workq); - -create_mgmt_workq_err: - kfree(pf_to_mgmt); - - return err; -} - -/** - * sphw_pf_to_mgmt_free - free PF to MGMT channel - * @hwdev: the pointer to hw device - **/ -void sphw_pf_to_mgmt_free(struct sphw_hwdev *hwdev) -{ - struct sphw_msg_pf_to_mgmt *pf_to_mgmt = hwdev->pf_to_mgmt; - - /* destroy workqueue before free related pf_to_mgmt resources in case of - * illegal resource access - */ - destroy_workqueue(pf_to_mgmt->workq); - sphw_api_cmd_free(pf_to_mgmt->cmd_chain); - - free_msg_buf(pf_to_mgmt); - kfree(pf_to_mgmt); -} - -void sphw_flush_mgmt_workq(void *hwdev) -{ - struct sphw_hwdev *dev = (struct sphw_hwdev *)hwdev; - - flush_workqueue(dev->aeqs->workq); - - if (sphw_func_type(dev) != TYPE_VF) - flush_workqueue(dev->pf_to_mgmt->workq); -} - -int sphw_api_cmd_read_ack(void *hwdev, u8 dest, const void *cmd, u16 size, void *ack, u16 ack_size) -{ - struct sphw_msg_pf_to_mgmt *pf_to_mgmt = NULL; - struct sphw_api_cmd_chain *chain = NULL; - - if (!hwdev || !cmd || (ack_size && !ack)) - return -EINVAL; - - pf_to_mgmt = ((struct sphw_hwdev *)hwdev)->pf_to_mgmt; - chain = pf_to_mgmt->cmd_chain[SPHW_API_CMD_POLL_READ]; - - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) - return -EPERM; - - return sphw_api_cmd_read(chain, dest, cmd, size, ack, ack_size); -} - -/** - * api cmd write or read bypass default use poll, if want to use aeq interrupt, - * please set wb_trigger_aeqe to 1 - **/ -int sphw_api_cmd_write_nack(void *hwdev, u8 dest, const void *cmd, u16 size) -{ - struct sphw_msg_pf_to_mgmt *pf_to_mgmt = NULL; - struct sphw_api_cmd_chain *chain = NULL; - - if (!hwdev || !size || !cmd) - return -EINVAL; - - pf_to_mgmt = ((struct sphw_hwdev *)hwdev)->pf_to_mgmt; - chain = pf_to_mgmt->cmd_chain[SPHW_API_CMD_POLL_WRITE]; - - if (!(((struct sphw_hwdev *)hwdev)->chip_present_flag)) - return -EPERM; - - return sphw_api_cmd_write(chain, dest, cmd, size); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt.h deleted file mode 100644 index 802336bd5cb1..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt.h +++ /dev/null @@ -1,106 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_MGMT_H -#define SPHW_MGMT_H - -#define SPHW_MGMT_WQ_NAME "sphw_mgmt" - -struct sphw_recv_msg { - void *msg; - - u16 msg_len; - enum sphw_mod_type mod; - u16 cmd; - u8 seq_id; - u16 msg_id; - int async_mgmt_to_pf; - - struct completion recv_done; -}; - -struct sphw_msg_head { - u8 status; - u8 version; - u8 resp_aeq_num; - u8 rsvd0[5]; -}; - -enum comm_pf_to_mgmt_event_state { - SEND_EVENT_UNINIT = 0, - SEND_EVENT_START, - SEND_EVENT_SUCCESS, - SEND_EVENT_FAIL, - SEND_EVENT_TIMEOUT, - SEND_EVENT_END, -}; - -enum sphw_mgmt_msg_cb_state { - SPHW_MGMT_MSG_CB_REG = 0, - SPHW_MGMT_MSG_CB_RUNNING, -}; - -struct sphw_msg_pf_to_mgmt { - struct sphw_hwdev *hwdev; - - /* Async cmd can not be scheduling */ - spinlock_t async_msg_lock; - struct semaphore sync_msg_lock; - - struct workqueue_struct *workq; - - void *async_msg_buf; - void *sync_msg_buf; - void *mgmt_ack_buf; - - struct sphw_recv_msg recv_msg_from_mgmt; - struct sphw_recv_msg recv_resp_msg_from_mgmt; - - u16 async_msg_id; - u16 sync_msg_id; - struct sphw_api_cmd_chain *cmd_chain[SPHW_API_CMD_MAX]; - - sphw_mgmt_msg_cb recv_mgmt_msg_cb[SPHW_MOD_HW_MAX]; - void *recv_mgmt_msg_data[SPHW_MOD_HW_MAX]; - unsigned long mgmt_msg_cb_state[SPHW_MOD_HW_MAX]; - - void *async_msg_cb_data[SPHW_MOD_HW_MAX]; - - /* lock when sending msg */ - spinlock_t sync_event_lock; - enum comm_pf_to_mgmt_event_state event_flag; -}; - -struct sphw_mgmt_msg_handle_work { - struct work_struct work; - struct sphw_msg_pf_to_mgmt *pf_to_mgmt; - - void *msg; - u16 msg_len; - - enum sphw_mod_type mod; - u16 cmd; - u16 msg_id; - - int async_mgmt_to_pf; -}; - -void sphw_mgmt_msg_aeqe_handler(void *handle, u8 *header, u8 size); - -int sphw_pf_to_mgmt_init(struct sphw_hwdev *hwdev); - -void sphw_pf_to_mgmt_free(struct sphw_hwdev *hwdev); - -int sphw_pf_to_mgmt_sync(void *hwdev, u8 mod, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, u32 timeout); -int sphw_pf_to_mgmt_async(void *hwdev, u8 mod, u16 cmd, const void *buf_in, u16 in_size); - -int sphw_pf_msg_to_mgmt_sync(void *hwdev, u8 mod, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, u32 timeout); - -int sphw_api_cmd_read_ack(void *hwdev, u8 dest, const void *cmd, u16 size, - void *ack, u16 ack_size); - -int sphw_api_cmd_write_nack(void *hwdev, u8 dest, const void *cmd, u16 size); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt_msg_base.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt_msg_base.h deleted file mode 100644 index 13f726895f58..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mgmt_msg_base.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_MGMT_MSG_BASE_H -#define SPHW_MGMT_MSG_BASE_H - -#define MGMT_MSG_CMD_OP_SET 1 -#define MGMT_MSG_CMD_OP_GET 0 - -#define MGMT_MSG_CMD_OP_START 1 -#define MGMT_MSG_CMD_OP_STOP 0 - -struct mgmt_msg_head { - u8 status; - u8 version; - u8 rsvd0[6]; -}; - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mt.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mt.h deleted file mode 100644 index d7fb58054202..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_mt.h +++ /dev/null @@ -1,533 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_MT_H -#define SPHW_MT_H - -#define NICTOOL_CMD_TYPE 0x18 - -struct api_cmd_rd { - u32 pf_id; - u8 dest; - u8 *cmd; - u16 size; - void *ack; - u16 ack_size; -}; - -struct api_cmd_wr { - u32 pf_id; - u8 dest; - u8 *cmd; - u16 size; -}; - -struct pf_dev_info { - u64 bar0_size; - u8 bus; - u8 slot; - u8 func; - u64 phy_addr; -}; - -/* Indicates the maximum number of interrupts that can be recorded. - * Subsequent interrupts are not recorded in FFM. - */ -#define FFM_RECORD_NUM_MAX 64 - -struct ffm_intr_info { - u8 node_id; - /* error level of the interrupt source */ - u8 err_level; - /* Classification by interrupt source properties */ - u16 err_type; - u32 err_csr_addr; - u32 err_csr_value; -}; - -struct ffm_intr_tm_info { - struct ffm_intr_info intr_info; - u8 times; - u8 sec; - u8 min; - u8 hour; - u8 mday; - u8 mon; - u16 year; -}; - -struct ffm_record_info { - u32 ffm_num; - u32 last_err_csr_addr; - u32 last_err_csr_value; - struct ffm_intr_tm_info ffm[FFM_RECORD_NUM_MAX]; -}; - -struct dbgtool_k_glb_info { - struct semaphore dbgtool_sem; - struct ffm_record_info *ffm; -}; - -struct msg_2_up { - u8 pf_id; - u8 mod; - u8 cmd; - void *buf_in; - u16 in_size; - void *buf_out; - u16 *out_size; -}; - -struct dbgtool_param { - union { - struct api_cmd_rd api_rd; - struct api_cmd_wr api_wr; - struct pf_dev_info *dev_info; - struct ffm_record_info *ffm_rd; - struct msg_2_up msg2up; - } param; - char chip_name[16]; -}; - -/* dbgtool command type */ -/* You can add commands as required. The dbgtool command can be - * used to invoke all interfaces of the kernel-mode x86 driver. - */ -enum dbgtool_cmd { - DBGTOOL_CMD_API_RD = 0, - DBGTOOL_CMD_API_WR, - DBGTOOL_CMD_FFM_RD, - DBGTOOL_CMD_FFM_CLR, - DBGTOOL_CMD_PF_DEV_INFO_GET, - DBGTOOL_CMD_MSG_2_UP, - DBGTOOL_CMD_FREE_MEM, - DBGTOOL_CMD_NUM -}; - -#define PF_MAX_SIZE 16 -#define BUSINFO_LEN 32 -#define SELF_TEST_BAR_ADDR_OFFSET 0x883c - -enum module_name { - SEND_TO_NPU = 1, - SEND_TO_MPU, - SEND_TO_SM, - - SEND_TO_HW_DRIVER, - SEND_TO_NIC_DRIVER, - SEND_TO_OVS_DRIVER, - SEND_TO_ROCE_DRIVER, - SEND_TO_TOE_DRIVER, - SEND_TO_IWAP_DRIVER, - SEND_TO_FC_DRIVER, - SEND_FCOE_DRIVER, -}; - -enum driver_cmd_type { - TX_INFO = 1, - Q_NUM, - TX_WQE_INFO, - TX_MAPPING, - RX_INFO, - RX_WQE_INFO, - RX_CQE_INFO, - UPRINT_FUNC_EN, - UPRINT_FUNC_RESET, - UPRINT_SET_PATH, - UPRINT_GET_STATISTICS, - FUNC_TYPE, - GET_FUNC_IDX, - GET_INTER_NUM, - CLOSE_TX_STREAM, - GET_DRV_VERSION, - CLEAR_FUNC_STASTIC, - GET_HW_STATS, - CLEAR_HW_STATS, - GET_SELF_TEST_RES, - GET_CHIP_FAULT_STATS, - NIC_RSVD1, - NIC_RSVD2, - NIC_RSVD3, - GET_CHIP_ID, - GET_SINGLE_CARD_INFO, - GET_FIRMWARE_ACTIVE_STATUS, - ROCE_DFX_FUNC, - GET_DEVICE_ID, - GET_PF_DEV_INFO, - CMD_FREE_MEM, - GET_LOOPBACK_MODE = 32, - SET_LOOPBACK_MODE, - SET_LINK_MODE, - SET_PF_BW_LIMIT, - GET_PF_BW_LIMIT, - ROCE_CMD, - GET_POLL_WEIGHT, - SET_POLL_WEIGHT, - GET_HOMOLOGUE, - SET_HOMOLOGUE, - GET_SSET_COUNT, - GET_SSET_ITEMS, - IS_DRV_IN_VM, - LRO_ADPT_MGMT, - SET_INTER_COAL_PARAM, - GET_INTER_COAL_PARAM, - GET_CHIP_INFO, - GET_NIC_STATS_LEN, - GET_NIC_STATS_STRING, - GET_NIC_STATS_INFO, - GET_PF_ID, - NIC_RSVD4, - NIC_RSVD5, - DCB_QOS_INFO, - DCB_PFC_STATE, - DCB_ETS_STATE, - DCB_STATE, - NIC_RSVD6, - NIC_RSVD7, - GET_ULD_DEV_NAME, - - RSS_CFG = 0x40, - RSS_INDIR, - PORT_ID, - - GET_FUNC_CAP = 0x50, - - GET_WIN_STAT = 0x60, - WIN_CSR_READ = 0x61, - WIN_CSR_WRITE = 0x62, - WIN_API_CMD_RD = 0x63, - - VM_COMPAT_TEST = 0xFF -}; - -enum api_chain_cmd_type { - API_CSR_READ, - API_CSR_WRITE -}; - -enum sm_cmd_type { - SM_CTR_RD32 = 1, - SM_CTR_RD64_PAIR, - SM_CTR_RD64, - SM_CTR_RD32_CLEAR, - SM_CTR_RD64_PAIR_CLEAR, - SM_CTR_RD64_CLEAR -}; - -struct cqm_stats { - atomic_t cqm_cmd_alloc_cnt; - atomic_t cqm_cmd_free_cnt; - atomic_t cqm_send_cmd_box_cnt; - atomic_t cqm_send_cmd_imm_cnt; - atomic_t cqm_db_addr_alloc_cnt; - atomic_t cqm_db_addr_free_cnt; - atomic_t cqm_fc_srq_create_cnt; - atomic_t cqm_srq_create_cnt; - atomic_t cqm_rq_create_cnt; - atomic_t cqm_qpc_mpt_create_cnt; - atomic_t cqm_nonrdma_queue_create_cnt; - atomic_t cqm_rdma_queue_create_cnt; - atomic_t cqm_rdma_table_create_cnt; - atomic_t cqm_qpc_mpt_delete_cnt; - atomic_t cqm_nonrdma_queue_delete_cnt; - atomic_t cqm_rdma_queue_delete_cnt; - atomic_t cqm_rdma_table_delete_cnt; - atomic_t cqm_func_timer_clear_cnt; - atomic_t cqm_func_hash_buf_clear_cnt; - atomic_t cqm_scq_callback_cnt; - atomic_t cqm_ecq_callback_cnt; - atomic_t cqm_nocq_callback_cnt; - atomic_t cqm_aeq_callback_cnt[112]; -}; - -enum sphw_fault_err_level { - FAULT_LEVEL_FATAL, - FAULT_LEVEL_SERIOUS_RESET, - FAULT_LEVEL_HOST, - FAULT_LEVEL_SERIOUS_FLR, - FAULT_LEVEL_GENERAL, - FAULT_LEVEL_SUGGESTION, - FAULT_LEVEL_MAX, -}; - -struct link_event_stats { - atomic_t link_down_stats; - atomic_t link_up_stats; -}; - -enum sphw_fault_type { - FAULT_TYPE_CHIP, - FAULT_TYPE_UCODE, - FAULT_TYPE_MEM_RD_TIMEOUT, - FAULT_TYPE_MEM_WR_TIMEOUT, - FAULT_TYPE_REG_RD_TIMEOUT, - FAULT_TYPE_REG_WR_TIMEOUT, - FAULT_TYPE_PHY_FAULT, - FAULT_TYPE_MAX, -}; - -struct fault_event_stats { - atomic_t chip_fault_stats[22][FAULT_LEVEL_MAX]; - atomic_t fault_type_stat[FAULT_TYPE_MAX]; - atomic_t pcie_fault_stats; -}; - -struct sphw_hw_stats { - atomic_t heart_lost_stats; - struct cqm_stats cqm_stats; - struct link_event_stats link_event_stats; - struct fault_event_stats fault_event_stats; -}; - -#ifndef IFNAMSIZ -#define IFNAMSIZ 16 -#endif - -struct pf_info { - char name[IFNAMSIZ]; - char bus_info[BUSINFO_LEN]; - u32 pf_type; -}; - -struct card_info { - struct pf_info pf[PF_MAX_SIZE]; - u32 pf_num; -}; - -struct spnic_nic_loop_mode { - u32 loop_mode; - u32 loop_ctrl; -}; - -enum spnic_show_set { - SHOW_SSET_IO_STATS = 1, -}; - -#define SPNIC_SHOW_ITEM_LEN 32 -struct spnic_show_item { - char name[SPNIC_SHOW_ITEM_LEN]; - u8 hexadecimal; /* 0: decimal , 1: Hexadecimal */ - u8 rsvd[7]; - u64 value; -}; - -#define SPHW_CHIP_FAULT_SIZE (110 * 1024) -#define MAX_DRV_BUF_SIZE 4096 - -struct nic_cmd_chip_fault_stats { - u32 offset; - u8 chip_fault_stats[MAX_DRV_BUF_SIZE]; -}; - -#define NIC_TOOL_MAGIC 'x' - -#define CARD_MAX_SIZE 16 -struct nic_card_id { - u32 id[CARD_MAX_SIZE]; - u32 num; -}; - -struct func_pdev_info { - u64 bar0_phy_addr; - u64 bar0_size; - u64 bar1_phy_addr; - u64 bar1_size; - u64 bar3_phy_addr; - u64 bar3_size; - u64 rsvd1[4]; -}; - -struct sphw_card_func_info { - u32 num_pf; - u32 rsvd0; - u64 usr_api_phy_addr; - struct func_pdev_info pdev_info[CARD_MAX_SIZE]; -}; - -struct wqe_info { - int q_id; - void *slq_handle; - unsigned int wqe_id; -}; - -#define MAX_VER_INFO_LEN 128 -struct drv_version_info { - char ver[MAX_VER_INFO_LEN]; -}; - -struct spnic_tx_hw_page { - u64 phy_addr; - u64 *map_addr; -}; - -struct nic_sq_info { - u16 q_id; - u16 pi; - u16 ci; /* sw_ci */ - u16 fi; /* hw_ci */ - u32 q_depth; - u16 pi_reverse; - u16 wqebb_size; - u8 priority; - u16 *ci_addr; - u64 cla_addr; - void *slq_handle; - struct spnic_tx_hw_page direct_wqe; - struct spnic_tx_hw_page doorbell; - u32 page_idx; - u32 glb_sq_id; -}; - -struct nic_rq_info { - u16 q_id; - u16 glb_rq_id; - u16 hw_pi; - u16 ci; /* sw_ci */ - u16 sw_pi; - u16 wqebb_size; - u16 q_depth; - u16 buf_len; - - void *slq_handle; - u64 ci_wqe_page_addr; - u64 ci_cla_tbl_addr; - - u8 coalesc_timer_cfg; - u8 pending_limt; - u16 msix_idx; - u32 msix_vector; -}; - -#define MT_EPERM 1 /* Operation not permitted */ -#define MT_EIO 2 /* I/O error */ -#define MT_EINVAL 3 /* Invalid argument */ -#define MT_EBUSY 4 /* Device or resource busy */ -#define MT_EOPNOTSUPP 0xFF /* Operation not supported */ - -struct mt_msg_head { - u8 status; - u8 rsvd1[3]; -}; - -#define MT_DCB_OPCODE_WR BIT(0) /* 1 - write, 0 - read */ -struct spnic_mt_qos_info { - struct mt_msg_head head; - - u16 op_code; - u8 valid_cos_bitmap; - u8 valid_up_bitmap; - u32 rsvd1; -}; - -struct spnic_mt_dcb_state { - struct mt_msg_head head; - - u16 op_code; - u8 state; - u8 rsvd; -}; - -#define MT_DCB_ETS_UP_TC BIT(1) -#define MT_DCB_ETS_UP_BW BIT(2) -#define MT_DCB_ETS_UP_PRIO BIT(3) -#define MT_DCB_ETS_TC_BW BIT(4) -#define MT_DCB_ETS_TC_PRIO BIT(5) - -#define DCB_UP_TC_NUM 0x8 -struct spnic_mt_ets_state { - struct mt_msg_head head; - - u16 op_code; - u8 up_tc[DCB_UP_TC_NUM]; - u8 up_bw[DCB_UP_TC_NUM]; - u8 tc_bw[DCB_UP_TC_NUM]; - u8 up_prio_bitmap; - u8 tc_prio_bitmap; - u32 rsvd; -}; - -#define MT_DCB_PFC_PFC_STATE BIT(1) -#define MT_DCB_PFC_PFC_PRI_EN BIT(2) -struct spnic_mt_pfc_state { - struct mt_msg_head head; - - u16 op_code; - u8 state; - u8 pfc_en_bitpamp; - u32 rsvd; -}; - -enum mt_api_type { - API_TYPE_MBOX = 1, - API_TYPE_API_CHAIN_BYPASS, - API_TYPE_API_CHAIN_TO_MPU, -}; - -struct npu_cmd_st { - u32 mod : 8; - u32 cmd : 8; - u32 ack_type : 3; - u32 direct_resp : 1; - u32 len : 12; -}; - -struct mpu_cmd_st { - u32 api_type : 8; - u32 mod : 8; - u32 cmd : 16; -}; - -struct msg_module { - char device_name[IFNAMSIZ]; - u32 module; - union { - u32 msg_formate; /* for driver */ - struct npu_cmd_st npu_cmd; - struct mpu_cmd_st mpu_cmd; - }; - u32 timeout; /* for mpu/npu cmd */ - u32 func_idx; - u32 buf_in_size; - u32 buf_out_size; - void *in_buf; - void *out_buf; - int bus_num; - u32 rsvd2[5]; -}; - -int alloc_buff_in(void *hwdev, struct msg_module *nt_msg, u32 in_size, void **buf_in); - -int alloc_buff_out(void *hwdev, struct msg_module *nt_msg, u32 out_size, void **buf_out); - -void free_buff_in(void *hwdev, struct msg_module *nt_msg, void *buf_in); - -void free_buff_out(void *hwdev, struct msg_module *nt_msg, void *buf_out); - -int copy_buf_out_to_user(struct msg_module *nt_msg, u32 out_size, void *buf_out); - -int get_func_type(void *hwdev, const void *buf_in, u32 in_size, void *buf_out, u32 *out_size); - -int get_func_id(void *hwdev, const void *buf_in, u32 in_size, void *buf_out, u32 *out_size); - -int get_drv_version(void *hwdev, const void *buf_in, u32 in_size, void *buf_out, u32 *out_size); - -int get_hw_driver_stats(const void *hwdev, const void *buf_in, u32 in_size, void *buf_out, - u32 *out_size); - -int clear_hw_driver_stats(void *hwdev, const void *buf_in, u32 in_size, void *buf_out, - u32 *out_size); - -int get_chip_faults_stats(const void *hwdev, const void *buf_in, u32 in_size, void *buf_out, - u32 *out_size); - -int get_chip_id_test(void *hwdev, const void *buf_in, u32 in_size, void *buf_out, u32 *out_size); - -int send_to_mpu(void *hwdev, struct msg_module *nt_msg, void *buf_in, u32 in_size, void *buf_out, - u32 *out_size); -int send_to_npu(void *hwdev, struct msg_module *nt_msg, void *buf_in, u32 in_size, void *buf_out, - u32 *out_size); - -int send_to_sm(void *hwdev, struct msg_module *nt_msg, void *buf_in, u32 in_size, void *buf_out, - u32 *out_size); - -#endif /* SPHW_MT_H_ */ diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.c deleted file mode 100644 index 20ebda15cda2..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.c +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/kernel.h> -#include <linux/semaphore.h> -#include <linux/workqueue.h> -#include <linux/dev_printk.h> - -#include "sphw_common.h" -#include "sphw_hwdev.h" -#include "sphw_profile.h" -#include "sphw_prof_adap.h" - -typedef bool (*sphw_is_match_prof)(struct sphw_hwdev *hwdev); - -static bool is_match_prof_default_adapter(struct sphw_hwdev *hwdev) -{ - /* always match default profile adapter in standard scene */ - return true; -} - -enum prof_adapter_type { - PROF_ADAP_TYPE_PANGEA = 1, - - /* Add prof adapter type before default */ - PROF_ADAP_TYPE_DEFAULT, -}; - -/** - * struct sphw_prof_adapter - custom scene's profile adapter - * @type: adapter type - * @match: Check whether the current function is used in the custom scene. - * Implemented in the current source file - * @init: When @match return true, the initialization function called in probe. - * Implemented in the source file of the custom scene - * @deinit: When @match return true, the deinitialization function called when - * remove. Implemented in the source file of the custom scene - */ -struct sphw_prof_adapter { - enum prof_adapter_type type; - sphw_is_match_prof match; - sphw_init_prof_attr init; - sphw_deinit_prof_attr deinit; -}; - -struct sphw_prof_adapter prof_adap_objs[] = { - /* Add prof adapter before default profile */ - { - .type = PROF_ADAP_TYPE_DEFAULT, - .match = is_match_prof_default_adapter, - .init = NULL, - .deinit = NULL, - }, -}; - -void sphw_init_profile_adapter(struct sphw_hwdev *hwdev) -{ - struct sphw_prof_adapter *prof_obj = NULL; - u16 num_adap = ARRAY_SIZE(prof_adap_objs); - u16 i; - - for (i = 0; i < num_adap; i++) { - prof_obj = &prof_adap_objs[i]; - if (!(prof_obj->match && prof_obj->match(hwdev))) - continue; - - hwdev->prof_adap_type = prof_obj->type; - hwdev->prof_attr = prof_obj->init ? - prof_obj->init(hwdev) : NULL; - sdk_info(hwdev->dev_hdl, "Find profile adapter, type: %d\n", - hwdev->prof_adap_type); - - break; - } -} - -void sphw_deinit_profile_adapter(struct sphw_hwdev *hwdev) -{ - struct sphw_prof_adapter *prof_obj = NULL; - u16 num_adap = ARRAY_SIZE(prof_adap_objs); - u16 i; - - for (i = 0; i < num_adap; i++) { - prof_obj = &prof_adap_objs[i]; - if (hwdev->prof_adap_type != prof_obj->type) - continue; - - if (prof_obj->deinit) - prof_obj->deinit(hwdev->prof_attr); - break; - } -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.h deleted file mode 100644 index f83d3a28c834..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_prof_adap.h +++ /dev/null @@ -1,49 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_PROF_ADAP_H -#define SPHW_PROF_ADAP_H - -#include <linux/workqueue.h> - -#include "sphw_profile.h" - -#define GET_PROF_ATTR_OPS(hwdev) \ - ((hwdev)->prof_attr ? (hwdev)->prof_attr->ops : NULL) - -static inline int sphw_get_work_cpu_affinity(struct sphw_hwdev *hwdev, - enum cpu_affinity_work_type type) -{ - struct sphw_prof_ops *ops = GET_PROF_ATTR_OPS(hwdev); - - if (ops && ops->get_work_cpu_affinity) - return ops->get_work_cpu_affinity(hwdev->prof_attr->priv_data, type); - - return WORK_CPU_UNBOUND; -} - -static inline void sphw_fault_post_process(struct sphw_hwdev *hwdev, u16 src, u16 level) -{ - struct sphw_prof_ops *ops = GET_PROF_ATTR_OPS(hwdev); - - if (ops && ops->fault_recover) - ops->fault_recover(hwdev->prof_attr->priv_data, src, level); -} - -static inline bool sphw_sw_feature_en(struct sphw_hwdev *hwdev, u64 feature_bit) -{ - if (!hwdev->prof_attr) - return false; - - return (hwdev->prof_attr->sw_feature_cap & feature_bit) && - (hwdev->prof_attr->dft_sw_feature & feature_bit); -} - -#define SW_FEATURE_EN(hwdev, f_bit) \ - sphw_sw_feature_en(hwdev, SPHW_SW_F_##f_bit) -#define SPHW_F_CHANNEL_LOCK_EN(hwdev) SW_FEATURE_EN(hwdev, CHANNEL_LOCK) - -void sphw_init_profile_adapter(struct sphw_hwdev *hwdev); -void sphw_deinit_profile_adapter(struct sphw_hwdev *hwdev); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_profile.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_profile.h deleted file mode 100644 index 0e1c6c91ba31..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_profile.h +++ /dev/null @@ -1,36 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_PROFILE_H -#define SPHW_PROFILE_H - -enum cpu_affinity_work_type { - WORK_TYPE_AEQ, - WORK_TYPE_MBOX, - WORK_TYPE_MGMT_MSG, - WORK_TYPE_COMM, -}; - -enum sphw_sw_features { - SPHW_SW_F_CHANNEL_LOCK = BIT(0), -}; - -struct sphw_prof_ops { - void (*fault_recover)(void *data, u16 src, u16 level); - int (*get_work_cpu_affinity)(void *data, u32 work_type); -}; - -struct sphw_prof_attr { - void *priv_data; - u64 hw_feature_cap; - u64 sw_feature_cap; - u64 dft_hw_feature; - u64 dft_sw_feature; - - struct sphw_prof_ops *ops; -}; - -typedef struct sphw_prof_attr *(*sphw_init_prof_attr)(void *hwdev); -typedef void (*sphw_deinit_prof_attr)(struct sphw_prof_attr *porf_attr); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_wq.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_wq.c deleted file mode 100644 index 0ec202dfc4d7..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_wq.c +++ /dev/null @@ -1,152 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <linux/device.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/spinlock.h> - -#include "sphw_common.h" -#include "sphw_wq.h" -#include "sphw_hwdev.h" - -#define WQ_MIN_DEPTH 64 -#define WQ_MAX_DEPTH 65536 -#define WQ_MAX_NUM_PAGES (PAGE_SIZE / sizeof(u64)) - -static int wq_init_wq_block(struct sphw_wq *wq) -{ - int i; - - if (WQ_IS_0_LEVEL_CLA(wq)) { - wq->wq_block_paddr = wq->wq_pages[0].align_paddr; - wq->wq_block_vaddr = wq->wq_pages[0].align_vaddr; - - return 0; - } - - if (wq->num_wq_pages > WQ_MAX_NUM_PAGES) { - sdk_err(wq->dev_hdl, "num_wq_pages exceed limit: %lu\n", - WQ_MAX_NUM_PAGES); - return -EFAULT; - } - - wq->wq_block_vaddr = dma_alloc_coherent(wq->dev_hdl, PAGE_SIZE, &wq->wq_block_paddr, - GFP_KERNEL); - if (!wq->wq_block_vaddr) { - sdk_err(wq->dev_hdl, "Failed to alloc wq block\n"); - return -ENOMEM; - } - - for (i = 0; i < wq->num_wq_pages; i++) - wq->wq_block_vaddr[i] = - cpu_to_be64(wq->wq_pages[i].align_paddr); - - return 0; -} - -static int wq_alloc_pages(struct sphw_wq *wq) -{ - int i, page_idx, err; - - wq->wq_pages = kcalloc(wq->num_wq_pages, sizeof(*wq->wq_pages), - GFP_KERNEL); - if (!wq->wq_pages) { - sdk_err(wq->dev_hdl, "Failed to alloc wq pages handle\n"); - return -ENOMEM; - } - - for (page_idx = 0; page_idx < wq->num_wq_pages; page_idx++) { - err = sphw_dma_alloc_coherent_align(wq->dev_hdl, wq->wq_page_size, - wq->wq_page_size, GFP_KERNEL, - &wq->wq_pages[page_idx]); - if (err) { - sdk_err(wq->dev_hdl, "Failed to alloc wq page\n"); - goto free_wq_pages; - } - } - - err = wq_init_wq_block(wq); - if (err) - goto free_wq_pages; - - return 0; - -free_wq_pages: - for (i = 0; i < page_idx; i++) - sphw_dma_free_coherent_align(wq->dev_hdl, &wq->wq_pages[i]); - - kfree(wq->wq_pages); - wq->wq_pages = NULL; - - return -ENOMEM; -} - -static void wq_free_pages(struct sphw_wq *wq) -{ - int i; - - if (!WQ_IS_0_LEVEL_CLA(wq)) - dma_free_coherent(wq->dev_hdl, PAGE_SIZE, wq->wq_block_vaddr, - wq->wq_block_paddr); - - for (i = 0; i < wq->num_wq_pages; i++) - sphw_dma_free_coherent_align(wq->dev_hdl, &wq->wq_pages[i]); - - kfree(wq->wq_pages); - wq->wq_pages = NULL; -} - -int sphw_wq_create(void *hwdev, struct sphw_wq *wq, u32 q_depth, u16 wqebb_size) -{ - struct sphw_hwdev *dev = hwdev; - u32 wq_page_size; - - if (!wq || !dev) { - pr_err("Invalid wq or dev_hdl\n"); - return -EINVAL; - } - - if (q_depth < WQ_MIN_DEPTH || q_depth > WQ_MAX_DEPTH || - (q_depth & (q_depth - 1)) || !wqebb_size || - (wqebb_size & (wqebb_size - 1))) { - sdk_err(dev->dev_hdl, "Wq q_depth(%u) or wqebb_size(%u) is invalid\n", - q_depth, wqebb_size); - return -EINVAL; - } - - wq_page_size = ALIGN(dev->wq_page_size, PAGE_SIZE); - - memset(wq, 0, sizeof(*wq)); - wq->dev_hdl = dev->dev_hdl; - wq->q_depth = q_depth; - wq->idx_mask = (u16)(q_depth - 1); - wq->wqebb_size = wqebb_size; - wq->wqebb_size_shift = (u16)ilog2(wq->wqebb_size); - wq->wq_page_size = wq_page_size; - - wq->wqebbs_per_page = wq_page_size / wqebb_size; - /* In case of wq_page_size is larger than q_depth * wqebb_size */ - if (wq->wqebbs_per_page > q_depth) - wq->wqebbs_per_page = q_depth; - wq->wqebbs_per_page_shift = (u16)ilog2(wq->wqebbs_per_page); - wq->wqebbs_per_page_mask = (u16)(wq->wqebbs_per_page - 1); - wq->num_wq_pages = (u16)(ALIGN(((u32)q_depth * wqebb_size), - wq_page_size) / wq_page_size); - - return wq_alloc_pages(wq); -} - -void sphw_wq_destroy(struct sphw_wq *wq) -{ - if (!wq) - return; - - wq_free_pages(wq); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_wq.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_wq.h deleted file mode 100644 index 01d564ca527a..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_wq.h +++ /dev/null @@ -1,119 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPHW_WQ_H -#define SPHW_WQ_H - -struct sphw_wq { - u16 cons_idx; - u16 prod_idx; - - u32 q_depth; - u16 idx_mask; - u16 wqebb_size_shift; - u16 num_wq_pages; - u32 wqebbs_per_page; - u16 wqebbs_per_page_shift; - u16 wqebbs_per_page_mask; - - struct sphw_dma_addr_align *wq_pages; - - dma_addr_t wq_block_paddr; - u64 *wq_block_vaddr; - - void *dev_hdl; - u32 wq_page_size; - u16 wqebb_size; -} ____cacheline_aligned; - -int sphw_wq_create(void *hwdev, struct sphw_wq *wq, u32 q_depth, u16 wqebb_size); -void sphw_wq_destroy(struct sphw_wq *wq); - -#define WQ_MASK_IDX(wq, idx) ((idx) & (wq)->idx_mask) -#define WQ_MASK_PAGE(wq, pg_idx) ((pg_idx) < (wq)->num_wq_pages ? (pg_idx) : 0) -#define WQ_PAGE_IDX(wq, idx) ((idx) >> (wq)->wqebbs_per_page_shift) -#define WQ_OFFSET_IN_PAGE(wq, idx) ((idx) & (wq)->wqebbs_per_page_mask) -#define WQ_GET_WQEBB_ADDR(wq, pg_idx, idx_in_pg) \ - ((u8 *)(wq)->wq_pages[pg_idx].align_vaddr + ((idx_in_pg) << (wq)->wqebb_size_shift)) -#define WQ_IS_0_LEVEL_CLA(wq) ((wq)->num_wq_pages == 1) - -static inline u16 sphw_wq_free_wqebbs(struct sphw_wq *wq) -{ - return wq->q_depth - ((wq->q_depth + wq->prod_idx - wq->cons_idx) & - wq->idx_mask) - 1; -} - -static inline bool sphw_wq_is_empty(struct sphw_wq *wq) -{ - return WQ_MASK_IDX(wq, wq->prod_idx) == WQ_MASK_IDX(wq, wq->cons_idx); -} - -static inline void *sphw_wq_get_one_wqebb(struct sphw_wq *wq, u16 *pi) -{ - *pi = WQ_MASK_IDX(wq, wq->prod_idx); - wq->prod_idx++; - - return WQ_GET_WQEBB_ADDR(wq, WQ_PAGE_IDX(wq, *pi), - WQ_OFFSET_IN_PAGE(wq, *pi)); -} - -static inline void *sphw_wq_get_multi_wqebbs(struct sphw_wq *wq, u16 num_wqebbs, u16 *prod_idx, - void **second_part_wqebbs_addr, - u16 *first_part_wqebbs_num) -{ - u32 pg_idx, off_in_page; - - *prod_idx = WQ_MASK_IDX(wq, wq->prod_idx); - wq->prod_idx += num_wqebbs; - - pg_idx = WQ_PAGE_IDX(wq, *prod_idx); - off_in_page = WQ_OFFSET_IN_PAGE(wq, *prod_idx); - - if (off_in_page + num_wqebbs > wq->wqebbs_per_page) { - /* wqe across wq page boundary */ - *second_part_wqebbs_addr = - WQ_GET_WQEBB_ADDR(wq, WQ_MASK_PAGE(wq, pg_idx + 1), 0); - *first_part_wqebbs_num = wq->wqebbs_per_page - off_in_page; - } else { - *second_part_wqebbs_addr = NULL; - *first_part_wqebbs_num = num_wqebbs; - } - - return WQ_GET_WQEBB_ADDR(wq, pg_idx, off_in_page); -} - -static inline void sphw_wq_put_wqebbs(struct sphw_wq *wq, u16 num_wqebbs) -{ - wq->cons_idx += num_wqebbs; -} - -static inline void *sphw_wq_wqebb_addr(struct sphw_wq *wq, u16 idx) -{ - return WQ_GET_WQEBB_ADDR(wq, WQ_PAGE_IDX(wq, idx), - WQ_OFFSET_IN_PAGE(wq, idx)); -} - -static inline void *sphw_wq_read_one_wqebb(struct sphw_wq *wq, u16 *cons_idx) -{ - *cons_idx = WQ_MASK_IDX(wq, wq->cons_idx); - - return sphw_wq_wqebb_addr(wq, *cons_idx); -} - -static inline u64 sphw_wq_get_first_wqe_page_addr(struct sphw_wq *wq) -{ - return wq->wq_pages[0].align_paddr; -} - -static inline void sphw_wq_reset(struct sphw_wq *wq) -{ - u16 pg_idx; - - wq->cons_idx = 0; - wq->prod_idx = 0; - - for (pg_idx = 0; pg_idx < wq->num_wq_pages; pg_idx++) - memset(wq->wq_pages[pg_idx].align_vaddr, 0, wq->wq_page_size); -} - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_dbg.c b/drivers/net/ethernet/ramaxel/spnic/spnic_dbg.c deleted file mode 100644 index 910baed023a5..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_dbg.c +++ /dev/null @@ -1,752 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/types.h> -#include <linux/semaphore.h> - -#include "sphw_mt.h" -#include "sphw_crm.h" -#include "spnic_nic_dev.h" -#include "spnic_nic_dbg.h" -#include "spnic_nic_qp.h" -#include "spnic_rx.h" -#include "spnic_tx.h" -#include "spnic_dcb.h" - -typedef int (*nic_driv_module)(struct spnic_nic_dev *nic_dev, const void *buf_in, u32 in_size, - void *buf_out, u32 *out_size); - -struct nic_drv_module_handle { - enum driver_cmd_type driv_cmd_name; - nic_driv_module driv_func; -}; - -int get_nic_drv_version(void *buf_out, u32 *out_size) -{ - struct drv_version_info *ver_info = buf_out; - - if (!buf_out) { - pr_err("Buf_out is NULL.\n"); - return -EINVAL; - } - - if (*out_size != sizeof(*ver_info)) { - pr_err("Unexpect out buf size from user :%u, expect: %lu\n", - *out_size, sizeof(*ver_info)); - return -EINVAL; - } - - snprintf(ver_info->ver, sizeof(ver_info->ver), "%s [compiled with the kernel]", - SPNIC_DRV_VERSION); - - return 0; -} - -static int get_tx_info(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - u16 q_id; - - if (!SPHW_CHANNEL_RES_VALID(nic_dev)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Netdev is down, can't get tx info\n"); - return -EFAULT; - } - - if (!buf_in || !buf_out) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Buf_in or buf_out is NULL.\n"); - return -EINVAL; - } - - q_id = *((u16 *)buf_in); - - return spnic_dbg_get_sq_info(nic_dev->hwdev, q_id, buf_out, *out_size); -} - -static int get_q_num(struct spnic_nic_dev *nic_dev, - const void *buf_in, u32 in_size, - void *buf_out, u32 *out_size) -{ - if (!SPHW_CHANNEL_RES_VALID(nic_dev)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Netdev is down, can't get queue number\n"); - return -EFAULT; - } - - if (!buf_out) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Get queue number para buf_out is NULL.\n"); - return -EINVAL; - } - - if (*out_size != sizeof(u16)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect out buf size from user: %u, expect: %lu\n", - *out_size, sizeof(u16)); - return -EINVAL; - } - - *((u16 *)buf_out) = nic_dev->q_params.num_qps; - - return 0; -} - -static int get_tx_wqe_info(struct spnic_nic_dev *nic_dev, - const void *buf_in, u32 in_size, - void *buf_out, u32 *out_size) -{ - const struct wqe_info *info = buf_in; - u16 wqebb_cnt = 1; - - if (!SPHW_CHANNEL_RES_VALID(nic_dev)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Netdev is down, can't get tx wqe info\n"); - return -EFAULT; - } - - if (!info || !buf_out) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Buf_in or buf_out is NULL.\n"); - return -EINVAL; - } - - return spnic_dbg_get_wqe_info(nic_dev->hwdev, (u16)info->q_id, - (u16)info->wqe_id, wqebb_cnt, - buf_out, (u16 *)out_size, SPNIC_SQ); -} - -static int get_rx_info(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - struct nic_rq_info *rq_info = buf_out; - u16 q_id; - int err; - - if (!SPHW_CHANNEL_RES_VALID(nic_dev)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Netdev is down, can't get rx info\n"); - return -EFAULT; - } - - if (!buf_in || !buf_out) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Buf_in or buf_out is NULL.\n"); - return -EINVAL; - } - - q_id = *((u16 *)buf_in); - - err = spnic_dbg_get_rq_info(nic_dev->hwdev, q_id, buf_out, *out_size); - - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Get rq info failed, ret is %d.\n", err); - return err; - } - - rq_info->ci = (u16)nic_dev->rxqs[q_id].cons_idx & - nic_dev->rxqs[q_id].q_mask; - - rq_info->sw_pi = nic_dev->rxqs[q_id].next_to_update; - rq_info->msix_vector = nic_dev->rxqs[q_id].irq_id; - - rq_info->coalesc_timer_cfg = nic_dev->rxqs[q_id].last_coalesc_timer_cfg; - rq_info->pending_limt = nic_dev->rxqs[q_id].last_pending_limt; - - return 0; -} - -static int get_rx_wqe_info(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - const struct wqe_info *info = buf_in; - u16 wqebb_cnt = 1; - - if (!SPHW_CHANNEL_RES_VALID(nic_dev)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Netdev is down, can't get rx wqe info\n"); - return -EFAULT; - } - - if (!info || !buf_out) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Buf_in or buf_out is NULL.\n"); - return -EINVAL; - } - - return spnic_dbg_get_wqe_info(nic_dev->hwdev, (u16)info->q_id, - (u16)info->wqe_id, wqebb_cnt, - buf_out, (u16 *)out_size, SPNIC_RQ); -} - -static int get_rx_cqe_info(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - const struct wqe_info *info = buf_in; - u16 q_id = 0; - u16 idx = 0; - - if (!SPHW_CHANNEL_RES_VALID(nic_dev)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Netdev is down, can't get rx cqe info\n"); - return -EFAULT; - } - - if (!info || !buf_out) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Buf_in or buf_out is NULL.\n"); - return -EINVAL; - } - - if (*out_size != sizeof(struct spnic_rq_cqe)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect out buf size from user :%u, expect: %lu\n", - *out_size, sizeof(struct spnic_rq_cqe)); - return -EINVAL; - } - q_id = (u16)info->q_id; - idx = (u16)info->wqe_id; - - if (q_id >= nic_dev->q_params.num_qps || - idx >= nic_dev->rxqs[q_id].q_depth) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Invalid q_id[%u] >= %u, or wqe idx[%u] >= %u.\n", - q_id, nic_dev->q_params.num_qps, idx, - nic_dev->rxqs[q_id].q_depth); - return -EFAULT; - } - - memcpy(buf_out, nic_dev->rxqs[q_id].rx_info[idx].cqe, - sizeof(struct spnic_rq_cqe)); - - return 0; -} - -static void clean_nicdev_stats(struct spnic_nic_dev *nic_dev) -{ - u64_stats_update_begin(&nic_dev->stats.syncp); - nic_dev->stats.netdev_tx_timeout = 0; - nic_dev->stats.tx_carrier_off_drop = 0; - nic_dev->stats.tx_invalid_qid = 0; - u64_stats_update_end(&nic_dev->stats.syncp); -} - -static int clear_func_static(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - int i; - - *out_size = 0; - clean_nicdev_stats(nic_dev); - for (i = 0; i < nic_dev->max_qps; i++) { - spnic_rxq_clean_stats(&nic_dev->rxqs[i].rxq_stats); - spnic_txq_clean_stats(&nic_dev->txqs[i].txq_stats); - } - - return 0; -} - -static int get_loopback_mode(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - struct spnic_nic_loop_mode *mode = buf_out; - - if (!out_size || !mode) - return -EINVAL; - - if (*out_size != sizeof(*mode)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect out buf size from user: %u, expect: %lu\n", - *out_size, sizeof(*mode)); - return -EINVAL; - } - - return spnic_get_loopback_mode(nic_dev->hwdev, (u8 *)&mode->loop_mode, - (u8 *)&mode->loop_ctrl); -} - -static int set_loopback_mode(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - const struct spnic_nic_loop_mode *mode = buf_in; - int err; - - if (!test_bit(SPNIC_INTF_UP, &nic_dev->flags)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Netdev is down, can't set loopback mode\n"); - return -EFAULT; - } - - if (!mode || !out_size || in_size != sizeof(*mode)) - return -EINVAL; - - if (*out_size != sizeof(*mode)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect out buf size from user: %u, expect: %lu\n", - *out_size, sizeof(*mode)); - return -EINVAL; - } - - err = spnic_set_loopback_mode(nic_dev->hwdev, (u8)mode->loop_mode, (u8)mode->loop_ctrl); - if (err == 0) - nicif_info(nic_dev, drv, nic_dev->netdev, "Set loopback mode %u en %u succeed\n", - mode->loop_mode, mode->loop_ctrl); - - return err; -} - -enum spnic_nic_link_mode { - SPNIC_LINK_MODE_AUTO = 0, - SPNIC_LINK_MODE_UP, - SPNIC_LINK_MODE_DOWN, - SPNIC_LINK_MODE_MAX, -}; - -static int set_link_mode_param_valid(struct spnic_nic_dev *nic_dev, - const void *buf_in, u32 in_size, - u32 *out_size) -{ - if (!test_bit(SPNIC_INTF_UP, &nic_dev->flags)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Netdev is down, can't set link mode\n"); - return -EFAULT; - } - - if (!buf_in || !out_size || - in_size != sizeof(enum spnic_nic_link_mode)) - return -EINVAL; - - if (*out_size != sizeof(enum spnic_nic_link_mode)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect out buf size from user: %u, expect: %lu\n", - *out_size, sizeof(enum spnic_nic_link_mode)); - return -EINVAL; - } - - return 0; -} - -static int set_link_mode(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - const enum spnic_nic_link_mode *link = buf_in; - u8 link_status; - - if (set_link_mode_param_valid(nic_dev, buf_in, in_size, out_size)) - return -EFAULT; - - switch (*link) { - case SPNIC_LINK_MODE_AUTO: - if (spnic_get_link_state(nic_dev->hwdev, &link_status)) - link_status = false; - spnic_link_status_change(nic_dev, (bool)link_status); - nicif_info(nic_dev, drv, nic_dev->netdev, - "Set link mode: auto succeed, now is link %s\n", - (link_status ? "up" : "down")); - break; - case SPNIC_LINK_MODE_UP: - spnic_link_status_change(nic_dev, true); - nicif_info(nic_dev, drv, nic_dev->netdev, - "Set link mode: up succeed\n"); - break; - case SPNIC_LINK_MODE_DOWN: - spnic_link_status_change(nic_dev, false); - nicif_info(nic_dev, drv, nic_dev->netdev, - "Set link mode: down succeed\n"); - break; - default: - nicif_err(nic_dev, drv, nic_dev->netdev, - "Invalid link mode %d to set\n", *link); - return -EINVAL; - } - - return 0; -} - -static int get_sset_count(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - u32 count; - - if (!buf_in || in_size != sizeof(u32) || !out_size || - *out_size != sizeof(u32) || !buf_out) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Invalid parameters, in_size: %u\n", - in_size); - return -EINVAL; - } - - switch (*((u32 *)buf_in)) { - case SHOW_SSET_IO_STATS: - count = spnic_get_io_stats_size(nic_dev); - break; - default: - count = 0; - break; - } - - *((u32 *)buf_out) = count; - - return 0; -} - -static int get_sset_stats(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - struct spnic_show_item *items = buf_out; - u32 sset, count, size; - int err; - - if (!buf_in || in_size != sizeof(u32) || !out_size || !buf_out) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Invalid parameters, in_size: %u\n", - in_size); - return -EINVAL; - } - - size = sizeof(u32); - err = get_sset_count(nic_dev, buf_in, in_size, &count, &size); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Get sset count failed, ret=%d\n", - err); - return -EINVAL; - } - if (count * sizeof(*items) != *out_size) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect out buf size from user :%u, expect: %lu\n", - *out_size, count * sizeof(*items)); - return -EINVAL; - } - - sset = *((u32 *)buf_in); - - switch (sset) { - case SHOW_SSET_IO_STATS: - spnic_get_io_stats(nic_dev, items); - break; - - default: - nicif_err(nic_dev, drv, nic_dev->netdev, "Unknown %u to get stats\n", - sset); - err = -EINVAL; - break; - } - - return err; -} - -static int dcb_mt_qos_map(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - const struct spnic_mt_qos_info *qos = buf_in; - struct spnic_mt_qos_info *qos_out = buf_out; - u8 up_cnt, up; - int err; - - if (!buf_out || !out_size || !buf_in) - return -EINVAL; - - if (*out_size != sizeof(*qos_out) || in_size != sizeof(*qos)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect buf size from user, in_size: %u, out_size: %u, expect: %lu\n", - in_size, *out_size, sizeof(*qos)); - return -EINVAL; - } - - memcpy(qos_out, qos, sizeof(*qos)); - qos_out->head.status = 0; - if (qos->op_code & MT_DCB_OPCODE_WR) { - up_cnt = 0; - for (up = 0; up < SPNIC_DCB_UP_MAX; up++) { - if (qos->valid_up_bitmap & BIT(up)) - up_cnt++; - } - - if (up_cnt != nic_dev->wanted_dcb_cfg.max_cos) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Invalid up bitmap: 0x%x", - qos->valid_up_bitmap); - qos_out->head.status = MT_EINVAL; - return 0; - } - - err = spnic_dcbcfg_set_up_bitmap(nic_dev, qos->valid_up_bitmap); - if (err) - qos_out->head.status = MT_EIO; - } else { - qos_out->valid_up_bitmap = - spnic_get_valid_up_bitmap(&nic_dev->wanted_dcb_cfg); - qos_out->valid_cos_bitmap = - nic_dev->wanted_dcb_cfg.valid_cos_bitmap; - } - - return 0; -} - -static int dcb_mt_dcb_state(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - const struct spnic_mt_dcb_state *dcb = buf_in; - struct spnic_mt_dcb_state *dcb_out = buf_out; - int err; - - if (!buf_in || !buf_out || !out_size) - return -EINVAL; - - if (*out_size != sizeof(*dcb_out) || in_size != sizeof(*dcb)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect buf size from user, in_size: %u, out_size: %u, expect: %lu\n", - in_size, *out_size, sizeof(*dcb)); - return -EINVAL; - } - - memcpy(dcb_out, dcb, sizeof(*dcb)); - dcb_out->head.status = 0; - if (dcb->op_code & MT_DCB_OPCODE_WR) { - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags) == dcb->state) - return 0; - - /* nic_mutex has been acquired by send_to_nic_driver and will - * also be acquired inside spnic_setup_tc - */ - mutex_unlock(&nic_dev->nic_mutex); - rtnl_lock(); - err = spnic_setup_tc(nic_dev->netdev, - dcb->state ? nic_dev->wanted_dcb_cfg.max_cos : 0); - rtnl_unlock(); - mutex_lock(&nic_dev->nic_mutex); - if (err) - dcb_out->head.status = MT_EIO; - } else { - dcb_out->state = !!test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags); - } - - return 0; -} - -static int dcb_mt_pfc_state(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - const struct spnic_mt_pfc_state *pfc = buf_in; - struct spnic_mt_pfc_state *pfc_out = buf_out; - u8 cur_pfc_state, cur_pfc_en_bitmap; - int err; - - if (!buf_in || !buf_out || !out_size) - return -EINVAL; - - if (*out_size != sizeof(*pfc_out) || in_size != sizeof(*pfc)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect buf size from user, in_size: %u, out_size: %u, expect: %lu\n", - in_size, *out_size, sizeof(*pfc)); - return -EINVAL; - } - - cur_pfc_state = spnic_dcbcfg_get_pfc_state(nic_dev); - cur_pfc_en_bitmap = spnic_dcbcfg_get_pfc_pri_en(nic_dev); - - memcpy(pfc_out, pfc, sizeof(*pfc)); - pfc_out->head.status = 0; - if (pfc->op_code & MT_DCB_OPCODE_WR) { - if (pfc->op_code & MT_DCB_PFC_PFC_STATE) - spnic_dcbcfg_set_pfc_state(nic_dev, pfc->state); - - if (pfc->op_code & MT_DCB_PFC_PFC_PRI_EN) - spnic_dcbcfg_set_pfc_pri_en(nic_dev, pfc->pfc_en_bitpamp); - - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - err = spnic_configure_dcb(nic_dev->netdev); - if (err) { - pfc_out->head.status = MT_EIO; - goto set_err; - } - } - } else { - pfc_out->state = cur_pfc_state; - pfc_out->pfc_en_bitpamp = cur_pfc_en_bitmap; - } - - return 0; - -set_err: - spnic_dcbcfg_set_pfc_state(nic_dev, cur_pfc_state); - spnic_dcbcfg_set_pfc_pri_en(nic_dev, cur_pfc_en_bitmap); - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - err = spnic_configure_dcb(nic_dev->netdev); - if (err) - nicif_warn(nic_dev, drv, nic_dev->netdev, - "Failed to rollback pfc config\n"); - } - return 0; -} - -static int dcb_mt_ets_state(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - const struct spnic_mt_ets_state *ets = buf_in; - struct spnic_mt_ets_state *ets_out = buf_out; - struct spnic_dcb_config dcb_cfg_backup; - int err; - - if (!buf_in || !buf_out || !out_size) - return -EINVAL; - - if (*out_size != sizeof(*ets_out) || in_size != sizeof(*ets)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect buf size from user, in_size: %u, out_size: %u, expect: %lu\n", - in_size, *out_size, sizeof(*ets)); - return -EINVAL; - } - - memcpy(ets_out, ets, sizeof(*ets)); - ets_out->head.status = 0; - if (ets->op_code & MT_DCB_OPCODE_WR) { - if (ets->op_code & (MT_DCB_ETS_UP_BW | MT_DCB_ETS_UP_PRIO)) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Not support to set up bw and up prio\n"); - ets_out->head.status = MT_EOPNOTSUPP; - return 0; - } - - dcb_cfg_backup = nic_dev->wanted_dcb_cfg; - - if (ets->op_code & MT_DCB_ETS_UP_TC) { - err = spnic_dcbcfg_set_ets_up_tc_map(nic_dev, ets->up_tc); - if (err) { - ets_out->head.status = MT_EIO; - return 0; - } - } - if (ets->op_code & MT_DCB_ETS_TC_BW) { - err = spnic_dcbcfg_set_ets_tc_bw(nic_dev, ets->tc_bw); - if (err) { - ets_out->head.status = MT_EIO; - goto set_err; - } - } - if (ets->op_code & MT_DCB_ETS_TC_PRIO) - spnic_dcbcfg_set_ets_tc_prio_type(nic_dev, ets->tc_prio_bitmap); - - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - err = spnic_configure_dcb(nic_dev->netdev); - if (err) { - ets_out->head.status = MT_EIO; - goto set_err; - } - } - } else { - spnic_dcbcfg_get_ets_up_tc_map(nic_dev, ets_out->up_tc); - spnic_dcbcfg_get_ets_tc_bw(nic_dev, ets_out->tc_bw); - spnic_dcbcfg_get_ets_tc_prio_type(nic_dev, &ets_out->tc_prio_bitmap); - } - - return 0; - -set_err: - nic_dev->wanted_dcb_cfg = dcb_cfg_backup; - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - err = spnic_configure_dcb(nic_dev->netdev); - if (err) - nicif_warn(nic_dev, drv, nic_dev->netdev, - "Failed to rollback ets config\n"); - } - - return 0; -} - -static int get_inter_num(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - u16 intr_num; - - intr_num = sphw_intr_num(nic_dev->hwdev); - - if (*out_size != sizeof(u16)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect out buf size from user :%u, expect: %lu\n", - *out_size, sizeof(u16)); - return -EFAULT; - } - *(u16 *)buf_out = intr_num; - - *out_size = sizeof(u16); - - return 0; -} - -static int get_netdev_name(struct spnic_nic_dev *nic_dev, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - if (*out_size != IFNAMSIZ) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Unexpect out buf size from user :%u, expect: %u\n", - *out_size, IFNAMSIZ); - return -EFAULT; - } - - strlcpy(buf_out, nic_dev->netdev->name, IFNAMSIZ); - - return 0; -} - -struct nic_drv_module_handle nic_driv_module_cmd_handle[] = { - {TX_INFO, get_tx_info}, - {Q_NUM, get_q_num}, - {TX_WQE_INFO, get_tx_wqe_info}, - {RX_INFO, get_rx_info}, - {RX_WQE_INFO, get_rx_wqe_info}, - {RX_CQE_INFO, get_rx_cqe_info}, - {GET_INTER_NUM, get_inter_num}, - {CLEAR_FUNC_STASTIC, clear_func_static}, - {GET_LOOPBACK_MODE, get_loopback_mode}, - {SET_LOOPBACK_MODE, set_loopback_mode}, - {SET_LINK_MODE, set_link_mode}, - {GET_SSET_COUNT, get_sset_count}, - {GET_SSET_ITEMS, get_sset_stats}, - {DCB_QOS_INFO, dcb_mt_qos_map}, - {DCB_STATE, dcb_mt_dcb_state}, - {DCB_PFC_STATE, dcb_mt_pfc_state}, - {DCB_ETS_STATE, dcb_mt_ets_state}, - {GET_ULD_DEV_NAME, get_netdev_name}, -}; - -static int send_to_nic_driver(struct spnic_nic_dev *nic_dev, - u32 cmd, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - int index, num_cmds = sizeof(nic_driv_module_cmd_handle) / - sizeof(nic_driv_module_cmd_handle[0]); - enum driver_cmd_type cmd_type = (enum driver_cmd_type)cmd; - int err = 0; - - mutex_lock(&nic_dev->nic_mutex); - for (index = 0; index < num_cmds; index++) { - if (cmd_type == - nic_driv_module_cmd_handle[index].driv_cmd_name) { - err = nic_driv_module_cmd_handle[index].driv_func - (nic_dev, buf_in, - in_size, buf_out, out_size); - break; - } - } - mutex_unlock(&nic_dev->nic_mutex); - - if (index == num_cmds) - pr_err("Can't find callback for %d\n", cmd_type); - - return err; -} - -int nic_ioctl(void *uld_dev, u32 cmd, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size) -{ - if (cmd == GET_DRV_VERSION) - return get_nic_drv_version(buf_out, out_size); - else if (!uld_dev) - return -EINVAL; - - return send_to_nic_driver(uld_dev, cmd, buf_in, - in_size, buf_out, out_size); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_dcb.c b/drivers/net/ethernet/ramaxel/spnic/spnic_dcb.c deleted file mode 100644 index 7108430e0618..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_dcb.c +++ /dev/null @@ -1,965 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> - -#include "sphw_crm.h" -#include "spnic_lld.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic_dev.h" -#include "spnic_dcb.h" - -#define DCB_CFG_CHG_ETS BIT(0) -#define DCB_CFG_CHG_PFC BIT(1) -#define DCB_CFG_CHG_UP_COS BIT(2) - -#define MAX_BW_PERCENT 100 - -void spnic_set_prio_tc_map(struct spnic_nic_dev *nic_dev) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->hw_dcb_cfg; - u8 valid_up_bitmap = spnic_get_valid_up_bitmap(dcb_cfg); - u8 default_tc = dcb_cfg->max_cos - 1; - u8 i, tc_id; - - /* use 0~max_cos-1 as tc for netdev */ - for (tc_id = 0, i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (dcb_cfg->valid_cos_bitmap & BIT(i)) { - netdev_set_prio_tc_map(nic_dev->netdev, - dcb_cfg->cos_cfg[i].up, tc_id); - tc_id++; - } - } - - /* set invalid up mapping to the default tc */ - for (i = 0; i < SPNIC_DCB_UP_MAX; i++) { - if (!(valid_up_bitmap & BIT(i))) - netdev_set_prio_tc_map(nic_dev->netdev, i, default_tc); - } -} - -void spnic_update_tx_db_cos(struct spnic_nic_dev *nic_dev) -{ - u8 i, valid_cos_bitmap, cos; - u16 num_rss; - - if (!test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - spnic_set_txq_cos(nic_dev, 0, nic_dev->q_params.num_qps, - nic_dev->hw_dcb_cfg.default_cos); - return; - } - - num_rss = nic_dev->q_params.num_rss; - valid_cos_bitmap = nic_dev->hw_dcb_cfg.valid_cos_bitmap; - for (i = 0; i < nic_dev->q_params.num_tc; i++) { - cos = (u8)(ffs(valid_cos_bitmap) - 1); - spnic_set_txq_cos(nic_dev, (u16)(i * num_rss), num_rss, cos); - valid_cos_bitmap &= (~BIT(cos)); - } -} - -int spnic_set_tx_cos_state(struct spnic_nic_dev *nic_dev) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->hw_dcb_cfg; - struct spnic_dcb_state dcb_state = {0}; - u8 default_cos, i; - int err; - - if (SPNIC_FUNC_IS_VF(nic_dev->hwdev)) { - err = spnic_get_pf_dcb_state(nic_dev->hwdev, &dcb_state); - if (err) { - spnic_err(nic_dev, drv, "Failed to get vf default cos\n"); - return err; - } - /* VF does not support DCB, use the default cos */ - dcb_cfg->default_cos = dcb_state.default_cos; - - return 0; - } - - default_cos = dcb_cfg->default_cos; - dcb_state.dcb_on = !!test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags); - dcb_state.default_cos = default_cos; - memset(dcb_state.up_cos, default_cos, sizeof(dcb_state.up_cos)); - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (dcb_cfg->valid_cos_bitmap & BIT(i)) - dcb_state.up_cos[dcb_cfg->cos_cfg[i].up] = i; - } - } - - err = spnic_set_dcb_state(nic_dev->hwdev, &dcb_state); - if (err) - spnic_err(nic_dev, drv, "Failed to set dcb state\n"); - - return err; -} - -static void setup_tc_reopen_handler(struct spnic_nic_dev *nic_dev, - const void *priv_data) -{ - u8 tc = *((u8 *)priv_data); - - if (tc) { - netdev_set_num_tc(nic_dev->netdev, tc); - spnic_set_prio_tc_map(nic_dev); - - set_bit(SPNIC_DCB_ENABLE, &nic_dev->flags); - } else { - netdev_reset_tc(nic_dev->netdev); - - clear_bit(SPNIC_DCB_ENABLE, &nic_dev->flags); - } - - spnic_set_tx_cos_state(nic_dev); -} - -int spnic_setup_tc(struct net_device *netdev, u8 tc) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_dyna_txrxq_params q_params = {0}; - u8 cur_tc; - int err; - - if (tc && test_bit(SPNIC_SAME_RXTX, &nic_dev->flags)) { - nicif_err(nic_dev, drv, netdev, "Failed to enable DCB while Symmetric RSS is enabled\n"); - return -EOPNOTSUPP; - } - - if (tc > nic_dev->hw_dcb_cfg.max_cos) { - nicif_err(nic_dev, drv, netdev, "Invalid num_tc: %u, max tc: %u\n", - tc, nic_dev->hw_dcb_cfg.max_cos); - return -EINVAL; - } - - if (tc & (tc - 1)) { - nicif_err(nic_dev, drv, netdev, - "Invalid num_tc: %u, must be power of 2\n", tc); - return -EINVAL; - } - - if (netif_running(netdev)) { - cur_tc = nic_dev->q_params.num_tc; - q_params = nic_dev->q_params; - q_params.num_tc = tc; - q_params.txqs_res = NULL; - q_params.rxqs_res = NULL; - q_params.irq_cfg = NULL; - - nicif_info(nic_dev, drv, netdev, "Change num_tc to %u, restarting channel\n", - tc); - err = spnic_change_channel_settings(nic_dev, &q_params, setup_tc_reopen_handler, - &tc); - if (err) { - if (cur_tc != nic_dev->q_params.num_tc) { - nicif_err(nic_dev, drv, netdev, - "Restore num_tc to %u\n", cur_tc); - /* In this case, the channel resource is - * invalid, so we can safely modify the number - * of tc in netdev. - */ - nic_dev->q_params.num_tc = cur_tc; - setup_tc_reopen_handler(nic_dev, &cur_tc); - } - nicif_err(nic_dev, drv, netdev, "Failed to change channel settings\n"); - return err; - } - } else { - setup_tc_reopen_handler(nic_dev, &tc); - spnic_update_num_qps(netdev); - } - - spnic_configure_dcb(netdev); - - return 0; -} - -/* Ucode thread timeout is 210ms, must be lagger then 210ms */ -#define SPNIC_WAIT_PORT_IO_STOP 250 - -static int spnic_stop_port_traffic_flow(struct spnic_nic_dev *nic_dev, bool wait) -{ - int err = 0; - - down(&nic_dev->dcb_sem); - - if (nic_dev->disable_port_cnt++ != 0) - goto out; - - err = spnic_force_port_disable(nic_dev); - if (err) { - spnic_err(nic_dev, drv, "Failed to disable port\n"); - goto set_port_err; - } - - err = spnic_set_port_funcs_state(nic_dev->hwdev, false); - if (err) { - spnic_err(nic_dev, drv, "Failed to disable all functions in port\n"); - goto set_port_funcs_err; - } - - spnic_info(nic_dev, drv, "Stop port traffic flow\n"); - - goto out; - -set_port_funcs_err: - spnic_force_set_port_state(nic_dev, !!netif_running(nic_dev->netdev)); - -set_port_err: -out: - if (err) - nic_dev->disable_port_cnt--; - - up(&nic_dev->dcb_sem); - if (!err && wait && nic_dev->netdev->reg_state == NETREG_REGISTERED) - msleep(SPNIC_WAIT_PORT_IO_STOP); - - return err; -} - -static int spnic_start_port_traffic_flow(struct spnic_nic_dev *nic_dev) -{ - int err; - - down(&nic_dev->dcb_sem); - - nic_dev->disable_port_cnt--; - if (nic_dev->disable_port_cnt > 0) { - up(&nic_dev->dcb_sem); - return 0; - } - - nic_dev->disable_port_cnt = 0; - up(&nic_dev->dcb_sem); - - err = spnic_force_set_port_state(nic_dev, !!netif_running(nic_dev->netdev)); - if (err) - spnic_err(nic_dev, drv, "Failed to disable port\n"); - - err = spnic_set_port_funcs_state(nic_dev->hwdev, true); - if (err) - spnic_err(nic_dev, drv, "Failed to disable all functions in port\n"); - - spnic_info(nic_dev, drv, "Start port traffic flow\n"); - - return err; -} - -static u8 get_cos_settings(u8 hw_valid_cos_bitmap, u8 *dst_valid_cos_bitmap) -{ - u8 support_cos = 0; - u8 num_cos, overflow; - u8 i; - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (hw_valid_cos_bitmap & BIT(i)) - support_cos++; - } - - num_cos = (u8)(1U << (u8)ilog2(support_cos)); - if (num_cos != support_cos) { - /* Remove unused cos id */ - overflow = support_cos - num_cos; - i = SPNIC_DCB_COS_MAX - 1; - while (overflow) { - if (hw_valid_cos_bitmap & BIT(i)) { - hw_valid_cos_bitmap &= (~BIT(i)); - overflow--; - } - - i--; - } - } - - *dst_valid_cos_bitmap = hw_valid_cos_bitmap; - - return num_cos; -} - -static int get_dft_valid_up_bitmap(struct spnic_nic_dev *nic_dev, u8 num_pri, - u8 *valid_up_bitmap) -{ - bool setted = false; - u8 up_bitmap = 0; - u8 up; - int err; - - err = spnic_get_chip_up_bitmap(nic_dev->pdev, &setted, &up_bitmap); - if (err) { - spnic_err(nic_dev, drv, "Get chip cos_up map failed\n"); - return -EFAULT; - } - - if (!setted) { - /* Use (num_cos-1)~0 as default user priority */ - for (up = 0; up < num_pri; up++) - up_bitmap |= (u8)BIT(up); - } - - err = spnic_set_chip_up_bitmap(nic_dev->pdev, up_bitmap); - if (err) { - spnic_err(nic_dev, drv, "Set chip cos_up map failed\n"); - return -EFAULT; - } - - *valid_up_bitmap = up_bitmap; - - return 0; -} - -u8 spnic_get_valid_up_bitmap(struct spnic_dcb_config *dcb_cfg) -{ - u8 valid_up_bitmap = 0; - u8 i; - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (dcb_cfg->valid_cos_bitmap & BIT(i)) - valid_up_bitmap |= (u8)BIT(dcb_cfg->cos_cfg[i].up); - } - - return valid_up_bitmap; -} - -static void update_valid_up_bitmap(struct spnic_dcb_config *dcb_cfg, - u8 valid_up_bitmap) -{ - u8 i, up; - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (!(dcb_cfg->valid_cos_bitmap & BIT(i))) { - dcb_cfg->cos_cfg[i].up = 0; - continue; - } - - /* get the highest priority */ - up = (u8)fls(valid_up_bitmap) - 1; - valid_up_bitmap &= (~BIT(up)); - - dcb_cfg->cos_cfg[i].up = up; - } -} - -static int init_default_dcb_cfg(struct spnic_nic_dev *nic_dev, - struct spnic_dcb_config *dcb_cfg) -{ - struct spnic_cos_cfg *cos_cfg = dcb_cfg->cos_cfg; - struct spnic_tc_cfg *tc_cfg = dcb_cfg->tc_cfg; - u8 valid_cos_bitmap, i; - u8 valid_up_bitmap = 0; - int err; - - valid_cos_bitmap = sphw_cos_valid_bitmap(nic_dev->hwdev); - if (!valid_cos_bitmap) { - spnic_err(nic_dev, drv, "None cos supported\n"); - return -EFAULT; - } - - dcb_cfg->max_cos = get_cos_settings(valid_cos_bitmap, - &dcb_cfg->valid_cos_bitmap); - dcb_cfg->default_cos = (u8)fls(dcb_cfg->valid_cos_bitmap) - 1; - - err = get_dft_valid_up_bitmap(nic_dev, dcb_cfg->max_cos, - &valid_up_bitmap); - if (err) - return err; - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - /* set all cos with 100 percent bw in default */ - cos_cfg[i].bw_pct = MAX_BW_PERCENT; - cos_cfg[i].prio_sp = 0; /* DWRR */ - cos_cfg[i].tc_id = 0; /* all cos mapping to tc0 */ - cos_cfg[i].up = 0; - } - - update_valid_up_bitmap(dcb_cfg, valid_up_bitmap); - - for (i = 0; i < SPNIC_DCB_TC_MAX; i++) { - /* tc0 with 100 percent bw in default */ - tc_cfg[i].bw_pct = (i == 0) ? MAX_BW_PERCENT : 0; - tc_cfg[i].prio_sp = 0; /* DWRR */ - } - - /* disable pfc */ - dcb_cfg->pfc_state = 0; - dcb_cfg->pfc_en_bitmap = 0; - - return 0; -} - -int spnic_dcb_init(struct spnic_nic_dev *nic_dev) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->wanted_dcb_cfg; - int err; - - if (SPNIC_FUNC_IS_VF(nic_dev->hwdev)) - return spnic_set_tx_cos_state(nic_dev); - - err = init_default_dcb_cfg(nic_dev, dcb_cfg); - if (err) { - spnic_err(nic_dev, drv, "Initialize dcb configuration failed\n"); - return err; - } - - spnic_info(nic_dev, drv, "Support num cos %u, default cos %u\n", - dcb_cfg->max_cos, dcb_cfg->default_cos); - - nic_dev->dcb_changes = DCB_CFG_CHG_ETS | DCB_CFG_CHG_PFC | - DCB_CFG_CHG_UP_COS; - - memcpy(&nic_dev->hw_dcb_cfg, &nic_dev->wanted_dcb_cfg, - sizeof(nic_dev->hw_dcb_cfg)); - - err = spnic_set_tx_cos_state(nic_dev); - if (err) { - spnic_err(nic_dev, drv, "Set tx cos state failed\n"); - return err; - } - - sema_init(&nic_dev->dcb_sem, 1); - - return 0; -} - -u32 spnic_sync_dcb_cfg(struct spnic_nic_dev *nic_dev, struct spnic_dcb_config *src_dcb_cfg) -{ - struct spnic_dcb_config *wanted_cfg = src_dcb_cfg; - struct spnic_dcb_config *hw_cfg = &nic_dev->hw_dcb_cfg; - u32 changes = 0; - - if (memcmp(hw_cfg->cos_cfg, wanted_cfg->cos_cfg, - sizeof(hw_cfg->cos_cfg))) { - memcpy(hw_cfg->cos_cfg, wanted_cfg->cos_cfg, - sizeof(hw_cfg->cos_cfg)); - changes |= DCB_CFG_CHG_ETS; - } - - if (memcmp(hw_cfg->tc_cfg, wanted_cfg->tc_cfg, - sizeof(hw_cfg->tc_cfg))) { - memcpy(hw_cfg->tc_cfg, wanted_cfg->tc_cfg, - sizeof(hw_cfg->tc_cfg)); - changes |= DCB_CFG_CHG_ETS; - } - - if (hw_cfg->pfc_state != wanted_cfg->pfc_state || - (wanted_cfg->pfc_state && - hw_cfg->pfc_en_bitmap != wanted_cfg->pfc_en_bitmap)) { - hw_cfg->pfc_state = wanted_cfg->pfc_state; - hw_cfg->pfc_en_bitmap = wanted_cfg->pfc_en_bitmap; - changes |= DCB_CFG_CHG_PFC; - } - - return changes; -} - -static int dcbcfg_set_hw_cos_up_map(struct spnic_nic_dev *nic_dev, - struct spnic_dcb_config *dcb_cfg) -{ - u8 cos_up_map[SPNIC_DCB_COS_MAX] = {0}; - int err; - u8 i; - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (!(dcb_cfg->valid_cos_bitmap & BIT(i))) - continue; - - cos_up_map[i] = dcb_cfg->cos_cfg[i].up; - } - - err = spnic_dcb_set_cos_up_map(nic_dev->hwdev, dcb_cfg->valid_cos_bitmap, - cos_up_map, SPNIC_DCB_COS_MAX); - if (err) - spnic_err(nic_dev, drv, "Set cos_up map failed\n"); - - return err; -} - -/* The sum of the cos bandwidth mapped to the same TC is 100 */ -static void adjust_cos_bw(u8 valid_cos_bitmap, u8 *cos_tc, u8 *cos_bw) -{ - u8 tc, cos, cos_num; - u16 bw_all, bw_remain; - - for (tc = 0; tc < SPNIC_DCB_TC_MAX; tc++) { - bw_all = 0; - cos_num = 0; - for (cos = 0; cos < SPNIC_DCB_COS_MAX; cos++) { - if (!(valid_cos_bitmap & BIT(cos)) || cos_tc[cos] != tc) - continue; - bw_all += cos_bw[cos]; - cos_num++; - } - - if (!bw_all || !cos_num) - continue; - - bw_remain = MAX_BW_PERCENT % cos_num; - for (cos = 0; cos < SPNIC_DCB_COS_MAX; cos++) { - if (!(valid_cos_bitmap & BIT(cos)) || cos_tc[cos] != tc) - continue; - - cos_bw[cos] = - (u8)(MAX_BW_PERCENT * cos_bw[cos] / bw_all); - - if (bw_remain) { - cos_bw[cos]++; - bw_remain--; - } - } - } -} - -static void dcbcfg_dump_configuration(struct spnic_nic_dev *nic_dev, - u8 *cos_tc, u8 *cos_bw, u8 *cos_prio, - u8 *tc_bw, u8 *tc_prio) -{ - u8 i; - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (!(nic_dev->hw_dcb_cfg.valid_cos_bitmap & BIT(i))) - continue; - - spnic_info(nic_dev, drv, "cos: %u, up: %u, tc: %u, bw: %u, prio: %u\n", - i, nic_dev->hw_dcb_cfg.cos_cfg[i].up, cos_tc[i], - cos_bw[i], cos_prio[i]); - } - - for (i = 0; i < nic_dev->hw_dcb_cfg.max_cos; i++) - spnic_info(nic_dev, drv, "tc: %u, bw: %u, prio: %u\n", - i, tc_bw[i], tc_prio[i]); -} - -static int dcbcfg_set_hw_ets(struct spnic_nic_dev *nic_dev, - struct spnic_dcb_config *dcb_cfg) -{ - u8 cos_tc[SPNIC_DCB_COS_MAX] = {0}; - u8 cos_bw[SPNIC_DCB_COS_MAX] = {0}; - u8 cos_prio[SPNIC_DCB_COS_MAX] = {0}; - u8 tc_bw[SPNIC_DCB_TC_MAX] = {0}; - u8 tc_prio[SPNIC_DCB_TC_MAX] = {0}; - int err; - u8 i; - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (!(dcb_cfg->valid_cos_bitmap & BIT(i))) - continue; - - cos_tc[i] = dcb_cfg->cos_cfg[i].tc_id; - cos_bw[i] = dcb_cfg->cos_cfg[i].bw_pct; - cos_prio[i] = dcb_cfg->cos_cfg[i].prio_sp; - } - - for (i = 0; i < SPNIC_DCB_TC_MAX; i++) { - tc_bw[i] = dcb_cfg->tc_cfg[i].bw_pct; - tc_prio[i] = dcb_cfg->tc_cfg[i].prio_sp; - } - - adjust_cos_bw(dcb_cfg->valid_cos_bitmap, cos_tc, cos_bw); - - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) - dcbcfg_dump_configuration(nic_dev, cos_tc, cos_bw, cos_prio, tc_bw, tc_prio); - - err = spnic_dcb_set_ets(nic_dev->hwdev, cos_tc, cos_bw, cos_prio, tc_bw, tc_prio); - if (err) { - spnic_err(nic_dev, drv, "Failed to set ets\n"); - return err; - } - - return 0; -} - -static int dcbcfg_set_hw_pfc(struct spnic_nic_dev *nic_dev, - struct spnic_dcb_config *dcb_cfg) -{ - u8 valid_up_bitmap = spnic_get_valid_up_bitmap(dcb_cfg); - u8 outof_range_pfc = (~valid_up_bitmap) & dcb_cfg->pfc_en_bitmap; - int err; - - if (dcb_cfg->pfc_state && outof_range_pfc) - spnic_info(nic_dev, drv, "PFC setting out of range, 0x%x will be ignored\n", - outof_range_pfc); - - err = spnic_dcb_set_pfc(nic_dev->hwdev, dcb_cfg->pfc_state, dcb_cfg->pfc_en_bitmap); - if (err) { - spnic_err(nic_dev, drv, "Failed to %s PFC\n", - dcb_cfg->pfc_state ? "enable" : "disable"); - return err; - } - - if (dcb_cfg->pfc_state) - spnic_info(nic_dev, drv, "Set PFC: 0x%x to hw done\n", - dcb_cfg->pfc_en_bitmap & valid_up_bitmap); - else - spnic_info(nic_dev, drv, "Disable PFC, enable tx/rx pause\n"); - - return 0; -} - -int spnic_dcbcfg_setall_to_hw(struct spnic_nic_dev *nic_dev, struct spnic_dcb_config *src_dcb_cfg) -{ - bool stop_traffic = false; - int err = 0; - - nic_dev->dcb_changes |= spnic_sync_dcb_cfg(nic_dev, src_dcb_cfg); - if (!nic_dev->dcb_changes) - return 0; - - /* hw does not support to change up cos mapping and cos tc mapping with - * traffic flow - */ - stop_traffic = !!(nic_dev->dcb_changes & - (DCB_CFG_CHG_ETS | DCB_CFG_CHG_UP_COS)); - if (stop_traffic) { - err = spnic_stop_port_traffic_flow(nic_dev, true); - if (err) - return err; - } - - if (nic_dev->dcb_changes & DCB_CFG_CHG_UP_COS) { - err = dcbcfg_set_hw_cos_up_map(nic_dev, &nic_dev->hw_dcb_cfg); - if (err) - goto out; - - nic_dev->dcb_changes &= (~DCB_CFG_CHG_UP_COS); - } - - if (nic_dev->dcb_changes & DCB_CFG_CHG_ETS) { - err = dcbcfg_set_hw_ets(nic_dev, &nic_dev->hw_dcb_cfg); - if (err) - goto out; - - nic_dev->dcb_changes &= (~DCB_CFG_CHG_ETS); - } - - if (nic_dev->dcb_changes & DCB_CFG_CHG_PFC) { - err = dcbcfg_set_hw_pfc(nic_dev, &nic_dev->hw_dcb_cfg); - if (err) - goto out; - - nic_dev->dcb_changes &= (~DCB_CFG_CHG_PFC); - } - -out: - if (stop_traffic) - spnic_start_port_traffic_flow(nic_dev); - - return err; -} - -int spnic_dcb_reset_hw_config(struct spnic_nic_dev *nic_dev) -{ - struct spnic_dcb_config dft_cfg = {0}; - int err; - - init_default_dcb_cfg(nic_dev, &dft_cfg); - err = spnic_dcbcfg_setall_to_hw(nic_dev, &dft_cfg); - if (err) { - spnic_err(nic_dev, drv, "Failed to reset hw dcb configuration\n"); - return err; - } - - spnic_info(nic_dev, drv, "Reset hardware DCB configuration done\n"); - - return 0; -} - -int spnic_configure_dcb(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) - return spnic_dcbcfg_setall_to_hw(nic_dev, &nic_dev->wanted_dcb_cfg); - else - return spnic_dcb_reset_hw_config(nic_dev); -} - -void spnic_dcbcfg_set_pfc_state(struct spnic_nic_dev *nic_dev, u8 pfc_state) -{ - nic_dev->wanted_dcb_cfg.pfc_state = pfc_state; -} - -u8 spnic_dcbcfg_get_pfc_state(struct spnic_nic_dev *nic_dev) -{ - return nic_dev->wanted_dcb_cfg.pfc_state; -} - -void spnic_dcbcfg_set_pfc_pri_en(struct spnic_nic_dev *nic_dev, u8 pfc_en_bitmap) -{ - nic_dev->wanted_dcb_cfg.pfc_en_bitmap = pfc_en_bitmap; -} - -u8 spnic_dcbcfg_get_pfc_pri_en(struct spnic_nic_dev *nic_dev) -{ - return nic_dev->wanted_dcb_cfg.pfc_en_bitmap; -} - -int spnic_dcbcfg_set_ets_up_tc_map(struct spnic_nic_dev *nic_dev, const u8 *up_tc_map) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->wanted_dcb_cfg; - u8 i; - - for (i = 0; i < SPNIC_DCB_UP_MAX; i++) { - if (!(dcb_cfg->valid_cos_bitmap & BIT(i))) - continue; - - /* TC id can't exceed max cos */ - if (up_tc_map[dcb_cfg->cos_cfg[i].up] >= dcb_cfg->max_cos) - return -EINVAL; - } - - for (i = 0; i < SPNIC_DCB_UP_MAX; i++) { - if (!(dcb_cfg->valid_cos_bitmap & BIT(i))) - continue; - - dcb_cfg->cos_cfg[i].tc_id = up_tc_map[dcb_cfg->cos_cfg[i].up]; - } - - return 0; -} - -void spnic_dcbcfg_get_ets_up_tc_map(struct spnic_nic_dev *nic_dev, u8 *up_tc_map) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->wanted_dcb_cfg; - struct spnic_cos_cfg *cos_cfg = dcb_cfg->cos_cfg; - u8 i; - - /* set unused up mapping to default tc */ - memset(up_tc_map, cos_cfg[dcb_cfg->default_cos].tc_id, - SPNIC_DCB_UP_MAX); - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - if (!(dcb_cfg->valid_cos_bitmap & BIT(i))) - continue; - - up_tc_map[cos_cfg[i].up] = cos_cfg[i].tc_id; - } -} - -int spnic_dcbcfg_set_ets_tc_bw(struct spnic_nic_dev *nic_dev, const u8 *tc_bw) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->wanted_dcb_cfg; - u8 bw_sum = 0; - u8 i; - - for (i = 0; i < SPNIC_DCB_TC_MAX; i++) { - /* cannot set bandwidth for unused tc */ - if (i >= dcb_cfg->max_cos && tc_bw[i] > 0) - return -EINVAL; - - bw_sum += tc_bw[i]; - } - - if (bw_sum != MAX_BW_PERCENT && bw_sum != 0) { - spnic_err(nic_dev, drv, "Invalid total bw %u\n", bw_sum); - return -EINVAL; - } - - for (i = 0; i < dcb_cfg->max_cos; i++) - dcb_cfg->tc_cfg[i].bw_pct = tc_bw[i]; - - return 0; -} - -void spnic_dcbcfg_get_ets_tc_bw(struct spnic_nic_dev *nic_dev, u8 *tc_bw) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->wanted_dcb_cfg; - u8 i; - - for (i = 0; i < dcb_cfg->max_cos; i++) - tc_bw[i] = dcb_cfg->tc_cfg[i].bw_pct; -} - -void spnic_dcbcfg_set_ets_tc_prio_type(struct spnic_nic_dev *nic_dev, u8 tc_prio_bitmap) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->wanted_dcb_cfg; - u8 i; - - for (i = 0; i < dcb_cfg->max_cos; i++) - dcb_cfg->tc_cfg[i].prio_sp = !!(tc_prio_bitmap & BIT(i)); -} - -void spnic_dcbcfg_get_ets_tc_prio_type(struct spnic_nic_dev *nic_dev, u8 *tc_prio_bitmap) -{ - struct spnic_dcb_config *dcb_cfg = &nic_dev->wanted_dcb_cfg; - u8 i; - - *tc_prio_bitmap = 0; - for (i = 0; i < dcb_cfg->max_cos; i++) { - if (dcb_cfg->tc_cfg[i].prio_sp) - *tc_prio_bitmap |= (u8)BIT(i); - } -} - -/* TODO: send a command to MPU, and MPU close all port traffic */ -static int stop_all_ports_flow(void *uld_array[], u32 num_dev) -{ - struct spnic_nic_dev *tmp_dev = NULL; - u32 i, idx; - int err; - - for (idx = 0; idx < num_dev; idx++) { - tmp_dev = (struct spnic_nic_dev *)uld_array[idx]; - err = spnic_stop_port_traffic_flow(tmp_dev, false); - if (err) { - nicif_err(tmp_dev, drv, tmp_dev->netdev, "Stop port traffic flow failed\n"); - goto stop_port_err; - } - } - - /* wait all traffic flow stopped */ - msleep(SPNIC_WAIT_PORT_IO_STOP); - - return 0; - -stop_port_err: - for (i = 0; i < idx; i++) { - tmp_dev = (struct spnic_nic_dev *)uld_array[i]; - spnic_start_port_traffic_flow(tmp_dev); - } - - return err; -} - -static void start_all_ports_flow(void *uld_array[], u32 num_dev) -{ - struct spnic_nic_dev *tmp_dev = NULL; - u32 idx; - - for (idx = 0; idx < num_dev; idx++) { - tmp_dev = (struct spnic_nic_dev *)uld_array[idx]; - spnic_start_port_traffic_flow(tmp_dev); - } -} - -int change_dev_cos_up_map(struct spnic_nic_dev *nic_dev, u8 valid_up_bitmap) -{ - struct net_device *netdev = nic_dev->netdev; - int err = 0; - - if (test_and_set_bit(SPNIC_DCB_UP_COS_SETTING, &nic_dev->dcb_flags)) { - nicif_warn(nic_dev, drv, netdev, - "Cos_up map setting in inprocess, please try again later\n"); - return -EFAULT; - } - - if (spnic_get_valid_up_bitmap(&nic_dev->wanted_dcb_cfg) == - valid_up_bitmap) { - nicif_err(nic_dev, drv, netdev, "Same up bitmap, don't need to change anything\n"); - err = 0; - goto out; - } - - nicif_info(nic_dev, drv, netdev, "Set valid_up_bitmap: 0x%x\n", - valid_up_bitmap); - - update_valid_up_bitmap(&nic_dev->wanted_dcb_cfg, valid_up_bitmap); - - nic_dev->dcb_changes = DCB_CFG_CHG_ETS | DCB_CFG_CHG_PFC | DCB_CFG_CHG_UP_COS; - - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - err = spnic_dcbcfg_setall_to_hw(nic_dev, &nic_dev->wanted_dcb_cfg); - if (err) { - nicif_err(nic_dev, drv, netdev, "Reconfig dcb to hw failed\n"); - goto out; - } - - /* Change up/tc map for netdev */ - spnic_set_prio_tc_map(nic_dev); - spnic_update_tx_db_cos(nic_dev); - } - - err = spnic_set_tx_cos_state(nic_dev); - -out: - clear_bit(SPNIC_DCB_UP_COS_SETTING, &nic_dev->dcb_flags); - - return err; -} - -int spnic_dcbcfg_set_up_bitmap(struct spnic_nic_dev *nic_dev, u8 valid_up_bitmap) -{ - struct spnic_nic_dev *tmp_dev = NULL; - void **uld_array = NULL; - u32 i, idx, num_dev = 0; - int err, rollback_err; - bool up_setted = false; - u8 old_valid_up_bitmap = 0; - u8 max_pf; - - /* Save old valid up bitmap, in case of set failed */ - err = spnic_get_chip_up_bitmap(nic_dev->pdev, &up_setted, &old_valid_up_bitmap); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Get old chip valid up bitmap failed\n"); - return -EFAULT; - } - - if (valid_up_bitmap == old_valid_up_bitmap) { - nicif_info(nic_dev, drv, nic_dev->netdev, "Same valid up bitmap, don't need to change anything\n"); - return 0; - } - - max_pf = sphw_max_pf_num(nic_dev->hwdev); - if (!max_pf) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Invalid max pf number\n"); - return -EFAULT; - } - - uld_array = kcalloc(max_pf, sizeof(void *), GFP_KERNEL); - if (!uld_array) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc uld_array\n"); - return -ENOMEM; - } - - /* Get all pf of this chip */ - err = spnic_get_pf_nic_uld_array(nic_dev->pdev, &num_dev, uld_array); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Get all pf private handle failed\n"); - err = -EFAULT; - goto out; - } - - err = stop_all_ports_flow(uld_array, num_dev); - if (err) - goto out; - - for (idx = 0; idx < num_dev; idx++) { - tmp_dev = (struct spnic_nic_dev *)uld_array[idx]; - err = change_dev_cos_up_map(tmp_dev, valid_up_bitmap); - if (err) { - nicif_err(tmp_dev, drv, tmp_dev->netdev, "Set cos_up map to hw failed\n"); - goto set_err; - } - } - - start_all_ports_flow(uld_array, num_dev); - - spnic_set_chip_up_bitmap(nic_dev->pdev, valid_up_bitmap); - kfree(uld_array); - - return 0; - -set_err: - /* undo all settings */ - for (i = 0; i <= idx; i++) { - tmp_dev = (struct spnic_nic_dev *)uld_array[i]; - rollback_err = change_dev_cos_up_map(tmp_dev, old_valid_up_bitmap); - if (rollback_err) - nicif_err(tmp_dev, drv, tmp_dev->netdev, "Failed to rollback cos_up map to hw\n"); - } - - start_all_ports_flow(uld_array, num_dev); - -out: - kfree(uld_array); - - return err; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_dcb.h b/drivers/net/ethernet/ramaxel/spnic/spnic_dcb.h deleted file mode 100644 index 48ef471237e2..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_dcb.h +++ /dev/null @@ -1,56 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_DCB_H -#define SPNIC_DCB_H - -enum SPNIC_DCB_FLAGS { - SPNIC_DCB_UP_COS_SETTING, - SPNIC_DCB_TRAFFIC_STOPPED, -}; - -struct spnic_cos_cfg { - u8 up; - u8 bw_pct; - u8 tc_id; - u8 prio_sp; /* 0 - DWRR, 1 - SP */ -}; - -struct spnic_tc_cfg { - u8 bw_pct; - u8 prio_sp; /* 0 - DWRR, 1 - SP */ - u16 rsvd; -}; - -struct spnic_dcb_config { - /* The num_tc of the protocol stack is also the same */ - u8 max_cos; - u8 default_cos; - u8 valid_cos_bitmap; - u8 rsvd1; - struct spnic_cos_cfg cos_cfg[SPNIC_DCB_COS_MAX]; - struct spnic_tc_cfg tc_cfg[SPNIC_DCB_TC_MAX]; - - u8 pfc_state; - u8 pfc_en_bitmap; - u16 rsvd2; -}; - -int spnic_dcb_init(struct spnic_nic_dev *nic_dev); -int spnic_dcb_reset_hw_config(struct spnic_nic_dev *nic_dev); -int spnic_configure_dcb(struct net_device *netdev); -int spnic_setup_tc(struct net_device *netdev, u8 tc); -u8 spnic_get_valid_up_bitmap(struct spnic_dcb_config *dcb_cfg); -void spnic_dcbcfg_set_pfc_state(struct spnic_nic_dev *nic_dev, u8 pfc_state); -u8 spnic_dcbcfg_get_pfc_state(struct spnic_nic_dev *nic_dev); -void spnic_dcbcfg_set_pfc_pri_en(struct spnic_nic_dev *nic_dev, u8 pfc_en_bitmap); -u8 spnic_dcbcfg_get_pfc_pri_en(struct spnic_nic_dev *nic_dev); -int spnic_dcbcfg_set_ets_up_tc_map(struct spnic_nic_dev *nic_dev, const u8 *up_tc_map); -void spnic_dcbcfg_get_ets_up_tc_map(struct spnic_nic_dev *nic_dev, u8 *up_tc_map); -int spnic_dcbcfg_set_ets_tc_bw(struct spnic_nic_dev *nic_dev, const u8 *tc_bw); -void spnic_dcbcfg_get_ets_tc_bw(struct spnic_nic_dev *nic_dev, u8 *tc_bw); -void spnic_dcbcfg_set_ets_tc_prio_type(struct spnic_nic_dev *nic_dev, u8 tc_prio_bitmap); -void spnic_dcbcfg_get_ets_tc_prio_type(struct spnic_nic_dev *nic_dev, u8 *tc_prio_bitmap); -int spnic_dcbcfg_set_up_bitmap(struct spnic_nic_dev *nic_dev, u8 valid_up_bitmap); -void spnic_update_tx_db_cos(struct spnic_nic_dev *nic_dev); -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_dev_mgmt.c b/drivers/net/ethernet/ramaxel/spnic/spnic_dev_mgmt.c deleted file mode 100644 index 6037645c0e8b..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_dev_mgmt.c +++ /dev/null @@ -1,811 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/io-mapping.h> -#include <linux/interrupt.h> -#include <net/addrconf.h> -#include <linux/time.h> -#include <linux/timex.h> -#include <linux/rtc.h> -#include <linux/debugfs.h> - -#include "sphw_common.h" -#include "sphw_mt.h" -#include "sphw_crm.h" -#include "spnic_lld.h" -#include "spnic_sriov.h" -#include "spnic_pci_id_tbl.h" -#include "spnic_dev_mgmt.h" - -#define SPNIC_WAIT_TOOL_CNT_TIMEOUT 10000 -#define SPNIC_WAIT_TOOL_MIN_USLEEP_TIME 9900 -#define SPNIC_WAIT_TOOL_MAX_USLEEP_TIME 10000 - -#define MAX_CARD_ID 64 -static unsigned long card_bit_map; - -LIST_HEAD(g_spnic_chip_list); - -void lld_dev_cnt_init(struct spnic_pcidev *pci_adapter) -{ - atomic_set(&pci_adapter->ref_cnt, 0); -} - -void lld_dev_hold(struct spnic_lld_dev *dev) -{ - struct spnic_pcidev *pci_adapter = pci_get_drvdata(dev->pdev); - - atomic_inc(&pci_adapter->ref_cnt); -} - -void lld_dev_put(struct spnic_lld_dev *dev) -{ - struct spnic_pcidev *pci_adapter = pci_get_drvdata(dev->pdev); - - atomic_dec(&pci_adapter->ref_cnt); -} - -void wait_lld_dev_unused(struct spnic_pcidev *pci_adapter) -{ - unsigned long end; - - end = jiffies + msecs_to_jiffies(SPNIC_WAIT_TOOL_CNT_TIMEOUT); - do { - if (!atomic_read(&pci_adapter->ref_cnt)) - return; - - /* if sleep 10ms, use usleep_range to be more precise */ - usleep_range(SPNIC_WAIT_TOOL_MIN_USLEEP_TIME, - SPNIC_WAIT_TOOL_MAX_USLEEP_TIME); - } while (time_before(jiffies, end)); -} - -enum spnic_lld_status { - SPNIC_NODE_CHANGE = BIT(0), -}; - -struct spnic_lld_lock { - /* lock for chip list */ - struct mutex lld_mutex; - unsigned long status; - atomic_t dev_ref_cnt; -}; - -struct spnic_lld_lock g_lld_lock; - -#define WAIT_LLD_DEV_HOLD_TIMEOUT (10 * 60 * 1000) /* 10minutes */ -#define WAIT_LLD_DEV_NODE_CHANGED (10 * 60 * 1000) /* 10minutes */ -#define WAIT_LLD_DEV_REF_CNT_EMPTY (2 * 60 * 1000) /* 2minutes */ -#define PRINT_TIMEOUT_INTERVAL 10000 -#define MS_PER_SEC 1000 -#define LLD_LOCK_MIN_USLEEP_TIME 900 -#define LLD_LOCK_MAX_USLEEP_TIME 1000 - -/* node in chip_node will changed, tools or driver can't get node - * during this situation - */ -void lld_lock_chip_node(void) -{ - unsigned long end; - bool timeout = true; - u32 loop_cnt; - - mutex_lock(&g_lld_lock.lld_mutex); - - loop_cnt = 0; - end = jiffies + msecs_to_jiffies(WAIT_LLD_DEV_NODE_CHANGED); - do { - if (!test_and_set_bit(SPNIC_NODE_CHANGE, &g_lld_lock.status)) { - timeout = false; - break; - } - - loop_cnt++; - if (loop_cnt % PRINT_TIMEOUT_INTERVAL == 0) - pr_warn("Wait for lld node change complete for %us\n", - loop_cnt / MS_PER_SEC); - - /* if sleep 1ms, use usleep_range to be more precise */ - usleep_range(LLD_LOCK_MIN_USLEEP_TIME, - LLD_LOCK_MAX_USLEEP_TIME); - } while (time_before(jiffies, end)); - - if (timeout && test_and_set_bit(SPNIC_NODE_CHANGE, &g_lld_lock.status)) - pr_warn("Wait for lld node change complete timeout when trying to get lld lock\n"); - - loop_cnt = 0; - timeout = true; - end = jiffies + msecs_to_jiffies(WAIT_LLD_DEV_NODE_CHANGED); - do { - if (!atomic_read(&g_lld_lock.dev_ref_cnt)) { - timeout = false; - break; - } - - loop_cnt++; - if (loop_cnt % PRINT_TIMEOUT_INTERVAL == 0) - pr_warn("Wait for lld dev unused for %us, reference count: %d\n", - loop_cnt / MS_PER_SEC, - atomic_read(&g_lld_lock.dev_ref_cnt)); - - /* if sleep 1ms, use usleep_range to be more precise */ - usleep_range(LLD_LOCK_MIN_USLEEP_TIME, - LLD_LOCK_MAX_USLEEP_TIME); - } while (time_before(jiffies, end)); - - if (timeout && atomic_read(&g_lld_lock.dev_ref_cnt)) - pr_warn("Wait for lld dev unused timeout\n"); - - mutex_unlock(&g_lld_lock.lld_mutex); -} - -void lld_unlock_chip_node(void) -{ - clear_bit(SPNIC_NODE_CHANGE, &g_lld_lock.status); -} - -/* When tools or other drivers want to get node of chip_node, use this function - * to prevent node be freed - */ -void lld_hold(void) -{ - unsigned long end; - u32 loop_cnt = 0; - - /* ensure there have not any chip node in changing */ - mutex_lock(&g_lld_lock.lld_mutex); - - end = jiffies + msecs_to_jiffies(WAIT_LLD_DEV_HOLD_TIMEOUT); - do { - if (!test_bit(SPNIC_NODE_CHANGE, &g_lld_lock.status)) - break; - - loop_cnt++; - - if (loop_cnt % PRINT_TIMEOUT_INTERVAL == 0) - pr_warn("Wait lld node change complete for %us\n", - loop_cnt / MS_PER_SEC); - /* if sleep 1ms, use usleep_range to be more precise */ - usleep_range(LLD_LOCK_MIN_USLEEP_TIME, - LLD_LOCK_MAX_USLEEP_TIME); - } while (time_before(jiffies, end)); - - if (test_bit(SPNIC_NODE_CHANGE, &g_lld_lock.status)) - pr_warn("Wait lld node change complete timeout when trying to hode lld dev\n"); - - atomic_inc(&g_lld_lock.dev_ref_cnt); - mutex_unlock(&g_lld_lock.lld_mutex); -} - -void lld_put(void) -{ - atomic_dec(&g_lld_lock.dev_ref_cnt); -} - -void spnic_lld_lock_init(void) -{ - mutex_init(&g_lld_lock.lld_mutex); - atomic_set(&g_lld_lock.dev_ref_cnt, 0); -} - -void spnic_get_all_chip_id(void *id_info) -{ - struct nic_card_id *card_id = (struct nic_card_id *)id_info; - struct card_node *chip_node = NULL; - int i = 0; - int id, err; - - lld_hold(); - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - err = sscanf(chip_node->chip_name, SPHW_CHIP_NAME "%d", &id); - if (err < 0) - pr_err("Failed to get spnic id\n"); - card_id->id[i] = id; - i++; - } - lld_put(); - card_id->num = i; -} - -void spnic_get_card_func_info_by_card_name(const char *chip_name, - struct sphw_card_func_info *card_func) -{ - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - struct func_pdev_info *pdev_info = NULL; - - card_func->num_pf = 0; - - lld_hold(); - - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - if (strncmp(chip_node->chip_name, chip_name, IFNAMSIZ)) - continue; - - list_for_each_entry(dev, &chip_node->func_list, node) { - if (sphw_func_type(dev->hwdev) == TYPE_VF) - continue; - - pdev_info = &card_func->pdev_info[card_func->num_pf]; - pdev_info->bar1_size = - pci_resource_len(dev->pcidev, SPNIC_PF_PCI_CFG_REG_BAR); - pdev_info->bar1_phy_addr = - pci_resource_start(dev->pcidev, SPNIC_PF_PCI_CFG_REG_BAR); - - pdev_info->bar3_size = - pci_resource_len(dev->pcidev, SPNIC_PCI_MGMT_REG_BAR); - pdev_info->bar3_phy_addr = - pci_resource_start(dev->pcidev, SPNIC_PCI_MGMT_REG_BAR); - - card_func->num_pf++; - if (card_func->num_pf >= CARD_MAX_SIZE) { - lld_put(); - return; - } - } - } - - lld_put(); -} - -static bool is_pcidev_match_chip_name(const char *ifname, struct spnic_pcidev *dev, - struct card_node *chip_node, enum func_type type) -{ - if (!strncmp(chip_node->chip_name, ifname, IFNAMSIZ)) { - if (sphw_func_type(dev->hwdev) != type) - return false; - return true; - } - - return false; -} - -static struct spnic_lld_dev *_get_lld_dev_by_chip_name(const char *ifname, enum func_type type) -{ - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - - lld_hold(); - - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - list_for_each_entry(dev, &chip_node->func_list, node) { - if (is_pcidev_match_chip_name(ifname, dev, chip_node, type)) { - lld_put(); - return &dev->lld_dev; - } - } - } - - lld_put(); - return NULL; -} - -static struct spnic_lld_dev *spnic_get_lld_dev_by_chip_name(const char *ifname) -{ - struct spnic_lld_dev *dev_hw_init = NULL; - struct spnic_lld_dev *dev = NULL; - - /*find hw init device first*/ - dev_hw_init = _get_lld_dev_by_chip_name(ifname, TYPE_UNKNOWN); - if (dev_hw_init) { - if (sphw_func_type(dev_hw_init->hwdev) == TYPE_PPF) - return dev_hw_init; - } - - dev = _get_lld_dev_by_chip_name(ifname, TYPE_PPF); - if (dev) { - if (dev_hw_init) - return dev_hw_init; - - return dev; - } - - dev = _get_lld_dev_by_chip_name(ifname, TYPE_PF); - if (dev) { - if (dev_hw_init) - return dev_hw_init; - - return dev; - } - - dev = _get_lld_dev_by_chip_name(ifname, TYPE_VF); - if (dev) - return dev; - - return NULL; -} - -static bool is_pcidev_match_dev_name(const char *ifname, struct spnic_pcidev *dev, - enum sphw_service_type type) -{ - enum sphw_service_type i; - char nic_uld_name[IFNAMSIZ] = {0}; - int err; - - if (type == SERVICE_T_MAX) { - for (i = SERVICE_T_OVS; i < SERVICE_T_MAX; i++) { - if (!strncmp(dev->uld_dev_name[i], ifname, IFNAMSIZ)) - return true; - } - } else { - if (!strncmp(dev->uld_dev_name[type], ifname, IFNAMSIZ)) - return true; - } - - err = spnic_get_uld_dev_name(dev, SERVICE_T_NIC, (char *)nic_uld_name); - if (!err) { - if (!strncmp(nic_uld_name, ifname, IFNAMSIZ)) - return true; - } - - return false; -} - -static struct spnic_lld_dev *spnic_get_lld_dev_by_dev_name(const char *ifname, - enum sphw_service_type type) -{ - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - - lld_hold(); - - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - list_for_each_entry(dev, &chip_node->func_list, node) { - if (is_pcidev_match_dev_name(ifname, dev, type)) { - lld_put(); - return &dev->lld_dev; - } - } - } - - lld_put(); - - return NULL; -} - -struct spnic_lld_dev *spnic_get_lld_dev_by_ifname(const char *ifname) -{ - struct spnic_lld_dev *dev = NULL; - - lld_hold(); - /* support search hwdev by chip name, net device name, - * or fc device name - */ - /* Find pcidev by chip_name first */ - dev = spnic_get_lld_dev_by_chip_name(ifname); - if (dev) - goto find_dev; - - /* If ifname not a chip name, - * find pcidev by FC name or netdevice name - */ - dev = spnic_get_lld_dev_by_dev_name(ifname, SERVICE_T_MAX); - if (!dev) { - lld_put(); - return NULL; - } - -find_dev: - lld_dev_hold(dev); - lld_put(); - return dev; -} - -void *spnic_get_hwdev_by_ifname(const char *ifname) -{ - struct spnic_lld_dev *dev = NULL; - - dev = spnic_get_lld_dev_by_ifname(ifname); - if (dev) - return dev->hwdev; - - return NULL; -} - -void *spnic_get_uld_dev_by_ifname(const char *ifname, enum sphw_service_type type) -{ - struct spnic_pcidev *dev = NULL; - struct spnic_lld_dev *lld_dev = NULL; - - if (type >= SERVICE_T_MAX) { - pr_err("Service type :%d is error\n", type); - return NULL; - } - - lld_dev = spnic_get_lld_dev_by_dev_name(ifname, type); - if (!lld_dev) - return NULL; - - dev = pci_get_drvdata(lld_dev->pdev); - if (dev) - return dev->uld_dev[type]; - - return NULL; -} - -static struct card_node *spnic_get_chip_node_by_hwdev(const void *hwdev) -{ - struct card_node *chip_node = NULL; - struct card_node *node_tmp = NULL; - struct spnic_pcidev *dev = NULL; - - if (!hwdev) - return NULL; - - lld_hold(); - - list_for_each_entry(node_tmp, &g_spnic_chip_list, node) { - if (!chip_node) { - list_for_each_entry(dev, &node_tmp->func_list, node) { - if (dev->hwdev == hwdev) { - chip_node = node_tmp; - break; - } - } - } - } - - lld_put(); - - return chip_node; -} - -int spnic_get_chip_name_by_hwdev(const void *hwdev, char *ifname) -{ - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - - if (!hwdev || !ifname) - return -EINVAL; - - lld_hold(); - - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - list_for_each_entry(dev, &chip_node->func_list, node) { - if (dev->hwdev == hwdev) { - strncpy(ifname, chip_node->chip_name, IFNAMSIZ - 1); - ifname[IFNAMSIZ - 1] = 0; - lld_put(); - return 0; - } - } - } - - lld_put(); - - return -ENXIO; -} - -void *spnic_get_uld_dev_by_pdev(struct pci_dev *pdev, enum sphw_service_type type) -{ - struct spnic_pcidev *pci_adapter = NULL; - - if (type >= SERVICE_T_MAX) { - pr_err("Service type :%d is error\n", type); - return NULL; - } - - pci_adapter = pci_get_drvdata(pdev); - if (pci_adapter) - return pci_adapter->uld_dev[type]; - - return NULL; -} - -void *spnic_get_ppf_hwdev_by_pdev(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = NULL; - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - - if (!pdev) - return NULL; - - pci_adapter = pci_get_drvdata(pdev); - if (!pci_adapter) - return NULL; - - chip_node = pci_adapter->chip_node; - lld_hold(); - list_for_each_entry(dev, &chip_node->func_list, node) { - if (dev->hwdev && sphw_func_type(dev->hwdev) == TYPE_PPF) { - lld_put(); - return dev->hwdev; - } - } - lld_put(); - - return NULL; -} - -/* NOTICE: nictool can't use this function, because this function can't keep - * tool context mutual exclusive with remove context - */ -void *spnic_get_ppf_uld_by_pdev(struct pci_dev *pdev, enum sphw_service_type type) -{ - struct spnic_pcidev *pci_adapter = NULL; - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - - if (!pdev) - return NULL; - - pci_adapter = pci_get_drvdata(pdev); - if (!pci_adapter) - return NULL; - - chip_node = pci_adapter->chip_node; - lld_hold(); - list_for_each_entry(dev, &chip_node->func_list, node) { - if (sphw_func_type(dev->hwdev) == TYPE_PPF) { - lld_put(); - return dev->uld_dev[type]; - } - } - lld_put(); - - return NULL; -} - -int spnic_get_pf_nic_uld_array(struct pci_dev *pdev, u32 *dev_cnt, void *array[]) -{ - struct spnic_pcidev *dev = pci_get_drvdata(pdev); - struct card_node *chip_node = NULL; - u32 cnt; - - if (!dev || !sphw_support_nic(dev->hwdev, NULL)) - return -EINVAL; - - lld_hold(); - - cnt = 0; - chip_node = dev->chip_node; - list_for_each_entry(dev, &chip_node->func_list, node) { - if (sphw_func_type(dev->hwdev) == TYPE_VF) - continue; - - array[cnt] = dev->uld_dev[SERVICE_T_NIC]; - cnt++; - } - lld_put(); - - *dev_cnt = cnt; - - return 0; -} - -static bool is_func_valid(struct spnic_pcidev *dev) -{ - if (sphw_func_type(dev->hwdev) == TYPE_VF) - return false; - - return true; -} - -int spnic_get_uld_dev_name(struct spnic_pcidev *dev, enum sphw_service_type type, char *ifname) -{ - u32 out_size = IFNAMSIZ; - - if (!g_uld_info[type].ioctl) - return -EFAULT; - - return g_uld_info[type].ioctl(dev->uld_dev[type], GET_ULD_DEV_NAME, - NULL, 0, ifname, &out_size); -} - -void spnic_get_card_info(const void *hwdev, void *bufin) -{ - struct card_node *chip_node = NULL; - struct card_info *info = (struct card_info *)bufin; - struct spnic_pcidev *dev = NULL; - void *fun_hwdev = NULL; - u32 i = 0; - - info->pf_num = 0; - - chip_node = spnic_get_chip_node_by_hwdev(hwdev); - if (!chip_node) - return; - - lld_hold(); - - list_for_each_entry(dev, &chip_node->func_list, node) { - if (!is_func_valid(dev)) - continue; - - fun_hwdev = dev->hwdev; - - if (sphw_support_nic(fun_hwdev, NULL)) { - if (dev->uld_dev[SERVICE_T_NIC]) { - info->pf[i].pf_type |= (u32)BIT(SERVICE_T_NIC); - spnic_get_uld_dev_name(dev, SERVICE_T_NIC, info->pf[i].name); - } - } - - /* to do : get other service info*/ - - if (sphw_func_for_mgmt(fun_hwdev)) - strlcpy(info->pf[i].name, "FOR_MGMT", IFNAMSIZ); - - strlcpy(info->pf[i].bus_info, pci_name(dev->pcidev), - sizeof(info->pf[i].bus_info)); - info->pf_num++; - i = info->pf_num; - } - - lld_put(); -} - -struct spnic_sriov_info *spnic_get_sriov_info_by_pcidev(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = NULL; - - if (!pdev) - return NULL; - - pci_adapter = pci_get_drvdata(pdev); - if (!pci_adapter) - return NULL; - - return &pci_adapter->sriov_info; -} - -void *spnic_get_hwdev_by_pcidev(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = NULL; - - if (!pdev) - return NULL; - - pci_adapter = pci_get_drvdata(pdev); - if (!pci_adapter) - return NULL; - - return pci_adapter->hwdev; -} - -bool spnic_is_in_host(void) -{ - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - - lld_hold(); - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - list_for_each_entry(dev, &chip_node->func_list, node) { - if (sphw_func_type(dev->hwdev) != TYPE_VF) { - lld_put(); - return true; - } - } - } - - lld_put(); - - return false; -} - -int spnic_get_chip_up_bitmap(struct pci_dev *pdev, bool *is_setted, u8 *valid_up_bitmap) -{ - struct spnic_pcidev *dev = pci_get_drvdata(pdev); - struct card_node *chip_node = NULL; - - if (!dev || !is_setted || !valid_up_bitmap) - return -EINVAL; - - chip_node = dev->chip_node; - *is_setted = chip_node->up_bitmap_setted; - if (chip_node->up_bitmap_setted) - *valid_up_bitmap = chip_node->valid_up_bitmap; - - return 0; -} - -int spnic_set_chip_up_bitmap(struct pci_dev *pdev, u8 valid_up_bitmap) -{ - struct spnic_pcidev *dev = pci_get_drvdata(pdev); - struct card_node *chip_node = NULL; - - if (!dev) - return -EINVAL; - - chip_node = dev->chip_node; - chip_node->up_bitmap_setted = true; - chip_node->valid_up_bitmap = valid_up_bitmap; - - return 0; -} - -static bool chip_node_is_exist(struct spnic_pcidev *pci_adapter, unsigned char *bus_number) -{ - struct card_node *chip_node = NULL; - - if (!pci_is_root_bus(pci_adapter->pcidev->bus)) - *bus_number = pci_adapter->pcidev->bus->number; - - if (*bus_number != 0) { - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - if (chip_node->bus_num == *bus_number) { - pci_adapter->chip_node = chip_node; - return true; - } - } - } else if (pci_adapter->pcidev->device == SPNIC_DEV_ID_VF || - pci_adapter->pcidev->device == SPNIC_DEV_ID_VF_HV) { - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - if (chip_node) { - pci_adapter->chip_node = chip_node; - return true; - } - } - } - - return false; -} - -int alloc_chip_node(struct spnic_pcidev *pci_adapter) -{ - struct card_node *chip_node = NULL; - unsigned char i; - unsigned char bus_number = 0; - - if (chip_node_is_exist(pci_adapter, &bus_number)) - return 0; - - for (i = 0; i < MAX_CARD_ID; i++) { - if (!test_and_set_bit(i, &card_bit_map)) - break; - } - - if (i == MAX_CARD_ID) { - sdk_err(&pci_adapter->pcidev->dev, "Failed to alloc card id\n"); - return -EFAULT; - } - - chip_node = kzalloc(sizeof(*chip_node), GFP_KERNEL); - if (!chip_node) { - clear_bit(i, &card_bit_map); - sdk_err(&pci_adapter->pcidev->dev, - "Failed to alloc chip node\n"); - return -ENOMEM; - } - - /* bus number */ - chip_node->bus_num = bus_number; - - snprintf(chip_node->chip_name, IFNAMSIZ, "%s%u", SPHW_CHIP_NAME, i); - - sdk_info(&pci_adapter->pcidev->dev, "Add new chip %s to global list succeed\n", - chip_node->chip_name); - - list_add_tail(&chip_node->node, &g_spnic_chip_list); - - INIT_LIST_HEAD(&chip_node->func_list); - pci_adapter->chip_node = chip_node; - - return 0; -} - -void free_chip_node(struct spnic_pcidev *pci_adapter) -{ - struct card_node *chip_node = pci_adapter->chip_node; - int id, err; - - if (list_empty(&chip_node->func_list)) { - list_del(&chip_node->node); - sdk_info(&pci_adapter->pcidev->dev, "Delete chip %s from global list succeed\n", - chip_node->chip_name); - err = sscanf(chip_node->chip_name, SPHW_CHIP_NAME "%d", &id); - if (err < 0) - sdk_err(&pci_adapter->pcidev->dev, "Failed to get spnic id\n"); - - clear_bit(id, &card_bit_map); - - kfree(chip_node); - } -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_dev_mgmt.h b/drivers/net/ethernet/ramaxel/spnic/spnic_dev_mgmt.h deleted file mode 100644 index 8f345769bec5..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_dev_mgmt.h +++ /dev/null @@ -1,78 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_DEV_MGMT_H -#define SPNIC_DEV_MGMT_H -#include <linux/types.h> -#include <linux/bitops.h> - -#define SPHW_CHIP_NAME "spnic" - -#define SPNIC_VF_PCI_CFG_REG_BAR 0 -#define SPNIC_PF_PCI_CFG_REG_BAR 1 - -#define SPNIC_PCI_INTR_REG_BAR 2 -#define SPNIC_PCI_MGMT_REG_BAR 3 /* Only PF have mgmt bar */ -#define SPNIC_PCI_DB_BAR 4 - -/* Structure pcidev private*/ -struct spnic_pcidev { - struct pci_dev *pcidev; - void *hwdev; - struct card_node *chip_node; - struct spnic_lld_dev lld_dev; - /* Record the service object address, - * such as spnic_dev and toe_dev, fc_dev - */ - void *uld_dev[SERVICE_T_MAX]; - /* Record the service object name */ - char uld_dev_name[SERVICE_T_MAX][IFNAMSIZ]; - /* It is a the global variable for driver to manage - * all function device linked list - */ - struct list_head node; - - bool disable_vf_load; - bool disable_srv_load[SERVICE_T_MAX]; - - void __iomem *cfg_reg_base; - void __iomem *intr_reg_base; - void __iomem *mgmt_reg_base; - u64 db_dwqe_len; - u64 db_base_phy; - void __iomem *db_base; - - /* lock for attach/detach uld */ - struct mutex pdev_mutex; - - struct spnic_sriov_info sriov_info; - - /* setted when uld driver processing event */ - unsigned long state; - struct pci_device_id id; - - atomic_t ref_cnt; -}; - -extern struct list_head g_spnic_chip_list; - -extern struct spnic_uld_info g_uld_info[SERVICE_T_MAX]; - -int alloc_chip_node(struct spnic_pcidev *pci_adapter); - -void free_chip_node(struct spnic_pcidev *pci_adapter); - -void lld_lock_chip_node(void); - -void lld_unlock_chip_node(void); - -void spnic_lld_lock_init(void); - -void lld_dev_cnt_init(struct spnic_pcidev *pci_adapter); -void wait_lld_dev_unused(struct spnic_pcidev *pci_adapter); - -int spnic_get_uld_dev_name(struct spnic_pcidev *dev, enum sphw_service_type type, char *ifname); - -void *spnic_get_hwdev_by_pcidev(struct pci_dev *pdev); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_ethtool.c b/drivers/net/ethernet/ramaxel/spnic/spnic_ethtool.c deleted file mode 100644 index e3a7e81a601b..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_ethtool.c +++ /dev/null @@ -1,994 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/if_vlan.h> -#include <linux/ethtool.h> - -#include "sphw_hw.h" -#include "sphw_crm.h" -#include "spnic_nic_dev.h" -#include "spnic_tx.h" -#include "spnic_rx.h" -#include "spnic_rss.h" - -#define COALESCE_ALL_QUEUE 0xFFFF -#define COALESCE_PENDING_LIMIT_UNIT 8 -#define COALESCE_TIMER_CFG_UNIT 5 -#define COALESCE_MAX_PENDING_LIMIT (255 * COALESCE_PENDING_LIMIT_UNIT) -#define COALESCE_MAX_TIMER_CFG (255 * COALESCE_TIMER_CFG_UNIT) - -static void spnic_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct pci_dev *pdev = nic_dev->pdev; - u8 mgmt_ver[SPHW_MGMT_VERSION_MAX_LEN] = {0}; - int err; - - strlcpy(info->driver, SPNIC_NIC_DRV_NAME, sizeof(info->driver)); - strlcpy(info->version, SPNIC_DRV_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, pci_name(pdev), sizeof(info->bus_info)); - - err = sphw_get_mgmt_version(nic_dev->hwdev, mgmt_ver, SPHW_MGMT_VERSION_MAX_LEN, - SPHW_CHANNEL_NIC); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to get fw version\n"); - return; - } - - snprintf(info->fw_version, sizeof(info->fw_version), "%s", mgmt_ver); -} - -static u32 spnic_get_msglevel(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - return nic_dev->msg_enable; -} - -static void spnic_set_msglevel(struct net_device *netdev, u32 data) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - nic_dev->msg_enable = data; - - nicif_info(nic_dev, drv, netdev, "Set message level: 0x%x\n", data); -} - -int spnic_nway_reset(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct nic_port_info port_info = {0}; - int err; - - err = spnic_get_port_info(nic_dev->hwdev, &port_info, SPHW_CHANNEL_NIC); - if (err) { - nicif_err(nic_dev, drv, netdev, - "Get port info failed\n"); - return -EFAULT; - } - - if (!port_info.autoneg_state) { - nicif_err(nic_dev, drv, netdev, "Autonegotiation is off, don't support to restart it\n"); - return -EINVAL; - } - - err = spnic_set_autoneg(nic_dev->hwdev, true); - if (err) { - nicif_err(nic_dev, drv, netdev, "Restart autonegotiation failed\n"); - return -EFAULT; - } - - nicif_info(nic_dev, drv, netdev, "Restart autonegotiation successfully\n"); - - return 0; -} - -static void spnic_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring, - struct kernel_ethtool_ringparam *kernel_ering, - struct netlink_ext_ack *extack) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - ring->rx_max_pending = SPNIC_MAX_RX_QUEUE_DEPTH; - ring->tx_max_pending = SPNIC_MAX_TX_QUEUE_DEPTH; - ring->rx_pending = nic_dev->rxqs[0].q_depth; - ring->tx_pending = nic_dev->txqs[0].q_depth; -} - -static void spnic_update_qp_depth(struct spnic_nic_dev *nic_dev, u32 sq_depth, u32 rq_depth) -{ - u16 i; - - nic_dev->q_params.sq_depth = sq_depth; - nic_dev->q_params.rq_depth = rq_depth; - for (i = 0; i < nic_dev->max_qps; i++) { - nic_dev->txqs[i].q_depth = sq_depth; - nic_dev->txqs[i].q_mask = sq_depth - 1; - nic_dev->rxqs[i].q_depth = rq_depth; - nic_dev->rxqs[i].q_mask = rq_depth - 1; - } -} - -static int check_ringparam_valid(struct net_device *netdev, struct ethtool_ringparam *ring) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - if (ring->rx_jumbo_pending || ring->rx_mini_pending) { - nicif_err(nic_dev, drv, netdev, - "Unsupported rx_jumbo_pending/rx_mini_pending\n"); - return -EINVAL; - } - - if (ring->tx_pending > SPNIC_MAX_TX_QUEUE_DEPTH || - ring->tx_pending < SPNIC_MIN_QUEUE_DEPTH || - ring->rx_pending > SPNIC_MAX_RX_QUEUE_DEPTH || - ring->rx_pending < SPNIC_MIN_QUEUE_DEPTH) { - nicif_err(nic_dev, drv, netdev, "Queue depth out of rang tx[%d-%d] rx[%d-%d]\n", - SPNIC_MIN_QUEUE_DEPTH, SPNIC_MAX_TX_QUEUE_DEPTH, - SPNIC_MIN_QUEUE_DEPTH, SPNIC_MAX_RX_QUEUE_DEPTH); - return -EINVAL; - } - - return 0; -} - -static int spnic_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring, - struct kernel_ethtool_ringparam *kernel_ering, - struct netlink_ext_ack *extack) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_dyna_txrxq_params q_params = {0}; - u32 new_sq_depth, new_rq_depth; - int err; - - err = check_ringparam_valid(netdev, ring); - if (err) - return err; - - new_sq_depth = (u32)(1U << (u16)ilog2(ring->tx_pending)); - new_rq_depth = (u32)(1U << (u16)ilog2(ring->rx_pending)); - - if (new_sq_depth == nic_dev->q_params.sq_depth && - new_rq_depth == nic_dev->q_params.rq_depth) - return 0; /* nothing to do */ - - nicif_info(nic_dev, drv, netdev, "Change Tx/Rx ring depth from %u/%u to %u/%u\n", - nic_dev->q_params.sq_depth, nic_dev->q_params.rq_depth, - new_sq_depth, new_rq_depth); - - if (!netif_running(netdev)) { - spnic_update_qp_depth(nic_dev, new_sq_depth, new_rq_depth); - } else { - q_params = nic_dev->q_params; - q_params.sq_depth = new_sq_depth; - q_params.rq_depth = new_rq_depth; - q_params.txqs_res = NULL; - q_params.rxqs_res = NULL; - q_params.irq_cfg = NULL; - - nicif_info(nic_dev, drv, netdev, "Restarting channel\n"); - err = spnic_change_channel_settings(nic_dev, &q_params, NULL, NULL); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to change channel settings\n"); - return -EFAULT; - } - } - - return 0; -} - -static int get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal, u16 queue) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_intr_coal_info *interrupt_info = NULL; - - if (queue == COALESCE_ALL_QUEUE) { - /* get tx/rx irq0 as default parameters */ - interrupt_info = &nic_dev->intr_coalesce[0]; - } else { - if (queue >= nic_dev->q_params.num_qps) { - nicif_err(nic_dev, drv, netdev, "Invalid queue_id: %u\n", queue); - return -EINVAL; - } - interrupt_info = &nic_dev->intr_coalesce[queue]; - } - - /* coalescs_timer is in unit of 5us */ - coal->rx_coalesce_usecs = interrupt_info->coalesce_timer_cfg * COALESCE_TIMER_CFG_UNIT; - /* coalescs_frams is in unit of 8 */ - coal->rx_max_coalesced_frames = interrupt_info->pending_limt * COALESCE_PENDING_LIMIT_UNIT; - - /* tx/rx use the same interrupt */ - coal->tx_coalesce_usecs = coal->rx_coalesce_usecs; - coal->tx_max_coalesced_frames = coal->rx_max_coalesced_frames; - coal->use_adaptive_rx_coalesce = nic_dev->adaptive_rx_coal; - - coal->pkt_rate_high = (u32)interrupt_info->pkt_rate_high; - coal->rx_coalesce_usecs_high = interrupt_info->rx_usecs_high * COALESCE_TIMER_CFG_UNIT; - coal->rx_max_coalesced_frames_high = interrupt_info->rx_pending_limt_high * - COALESCE_PENDING_LIMIT_UNIT; - - coal->pkt_rate_low = (u32)interrupt_info->pkt_rate_low; - coal->rx_coalesce_usecs_low = interrupt_info->rx_usecs_low * - COALESCE_TIMER_CFG_UNIT; - coal->rx_max_coalesced_frames_low = interrupt_info->rx_pending_limt_low * - COALESCE_PENDING_LIMIT_UNIT; - - return 0; -} - -static int set_queue_coalesce(struct spnic_nic_dev *nic_dev, u16 q_id, - struct spnic_intr_coal_info *coal) -{ - struct spnic_intr_coal_info *intr_coal; - struct interrupt_info info = {0}; - struct net_device *netdev = nic_dev->netdev; - int err; - - intr_coal = &nic_dev->intr_coalesce[q_id]; - if (intr_coal->coalesce_timer_cfg != coal->coalesce_timer_cfg || - intr_coal->pending_limt != coal->pending_limt) - intr_coal->user_set_intr_coal_flag = 1; - - intr_coal->coalesce_timer_cfg = coal->coalesce_timer_cfg; - intr_coal->pending_limt = coal->pending_limt; - intr_coal->pkt_rate_low = coal->pkt_rate_low; - intr_coal->rx_usecs_low = coal->rx_usecs_low; - intr_coal->rx_pending_limt_low = coal->rx_pending_limt_low; - intr_coal->pkt_rate_high = coal->pkt_rate_high; - intr_coal->rx_usecs_high = coal->rx_usecs_high; - intr_coal->rx_pending_limt_high = coal->rx_pending_limt_high; - - /* netdev not running or qp not in using, - * don't need to set coalesce to hw - */ - if (!test_bit(SPNIC_INTF_UP, &nic_dev->flags) || - q_id >= nic_dev->q_params.num_qps || nic_dev->adaptive_rx_coal) - return 0; - - info.msix_index = nic_dev->q_params.irq_cfg[q_id].msix_entry_idx; - info.lli_set = 0; - info.interrupt_coalesc_set = 1; - info.coalesc_timer_cfg = intr_coal->coalesce_timer_cfg; - info.pending_limt = intr_coal->pending_limt; - info.resend_timer_cfg = intr_coal->resend_timer_cfg; - nic_dev->rxqs[q_id].last_coalesc_timer_cfg = intr_coal->coalesce_timer_cfg; - nic_dev->rxqs[q_id].last_pending_limt = intr_coal->pending_limt; - err = sphw_set_interrupt_cfg(nic_dev->hwdev, info, SPHW_CHANNEL_NIC); - if (err) - nicif_warn(nic_dev, drv, netdev, "Failed to set queue%u coalesce", q_id); - - return err; -} - -static int is_coalesce_exceed_limit(struct net_device *netdev, - const struct ethtool_coalesce *coal) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - if (coal->rx_coalesce_usecs > COALESCE_MAX_TIMER_CFG) { - nicif_err(nic_dev, drv, netdev, "rx_coalesce_usecs out of range[%d-%d]\n", 0, - COALESCE_MAX_TIMER_CFG); - return -EOPNOTSUPP; - } - - if (coal->rx_max_coalesced_frames > COALESCE_MAX_PENDING_LIMIT) { - nicif_err(nic_dev, drv, netdev, "rx_max_coalesced_frames out of range[%d-%d]\n", 0, - COALESCE_MAX_PENDING_LIMIT); - return -EOPNOTSUPP; - } - - if (coal->rx_coalesce_usecs_low > COALESCE_MAX_TIMER_CFG) { - nicif_err(nic_dev, drv, netdev, "rx_coalesce_usecs_low out of range[%d-%d]\n", 0, - COALESCE_MAX_TIMER_CFG); - return -EOPNOTSUPP; - } - - if (coal->rx_max_coalesced_frames_low > COALESCE_MAX_PENDING_LIMIT) { - nicif_err(nic_dev, drv, netdev, "rx_max_coalesced_frames_low out of range[%d-%d]\n", - 0, COALESCE_MAX_PENDING_LIMIT); - return -EOPNOTSUPP; - } - - if (coal->rx_coalesce_usecs_high > COALESCE_MAX_TIMER_CFG) { - nicif_err(nic_dev, drv, netdev, "rx_coalesce_usecs_high out of range[%d-%d]\n", 0, - COALESCE_MAX_TIMER_CFG); - return -EOPNOTSUPP; - } - - if (coal->rx_max_coalesced_frames_high > COALESCE_MAX_PENDING_LIMIT) { - nicif_err(nic_dev, drv, netdev, "rx_max_coalesced_frames_high out of range[%d-%d]\n", - 0, COALESCE_MAX_PENDING_LIMIT); - return -EOPNOTSUPP; - } - - return 0; -} - -static int is_coalesce_legal(struct net_device *netdev, - const struct ethtool_coalesce *coal) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct ethtool_coalesce tmp_coal = {0}; - int err; - - if (coal->rx_coalesce_usecs != coal->tx_coalesce_usecs) { - nicif_err(nic_dev, drv, netdev, "tx-usecs must be equal to rx-usecs\n"); - return -EINVAL; - } - - if (coal->rx_max_coalesced_frames != coal->tx_max_coalesced_frames) { - nicif_err(nic_dev, drv, netdev, "tx-frames must be equal to rx-frames\n"); - return -EINVAL; - } - - tmp_coal.cmd = coal->cmd; - tmp_coal.rx_coalesce_usecs = coal->rx_coalesce_usecs; - tmp_coal.rx_max_coalesced_frames = coal->rx_max_coalesced_frames; - tmp_coal.tx_coalesce_usecs = coal->tx_coalesce_usecs; - tmp_coal.tx_max_coalesced_frames = coal->tx_max_coalesced_frames; - tmp_coal.use_adaptive_rx_coalesce = coal->use_adaptive_rx_coalesce; - - tmp_coal.pkt_rate_low = coal->pkt_rate_low; - tmp_coal.rx_coalesce_usecs_low = coal->rx_coalesce_usecs_low; - tmp_coal.rx_max_coalesced_frames_low = coal->rx_max_coalesced_frames_low; - - tmp_coal.pkt_rate_high = coal->pkt_rate_high; - tmp_coal.rx_coalesce_usecs_high = coal->rx_coalesce_usecs_high; - tmp_coal.rx_max_coalesced_frames_high = coal->rx_max_coalesced_frames_high; - - if (memcmp(coal, &tmp_coal, sizeof(struct ethtool_coalesce))) { - nicif_err(nic_dev, drv, netdev, "Only support to change rx/tx-usecs and rx/tx-frames\n"); - return -EOPNOTSUPP; - } - - err = is_coalesce_exceed_limit(netdev, coal); - if (err) - return err; - - if (coal->rx_coalesce_usecs_low / COALESCE_TIMER_CFG_UNIT >= - coal->rx_coalesce_usecs_high / COALESCE_TIMER_CFG_UNIT) { - nicif_err(nic_dev, drv, netdev, - "coalesce_usecs_high(%u) must more than coalesce_usecs_low(%u), after dividing %d usecs unit\n", - coal->rx_coalesce_usecs_high, - coal->rx_coalesce_usecs_low, - COALESCE_TIMER_CFG_UNIT); - return -EOPNOTSUPP; - } - - if (coal->rx_max_coalesced_frames_low / COALESCE_PENDING_LIMIT_UNIT >= - coal->rx_max_coalesced_frames_high / COALESCE_PENDING_LIMIT_UNIT) { - nicif_err(nic_dev, drv, netdev, - "coalesced_frames_high(%u) must more than coalesced_frames_low(%u),after dividing %d frames unit\n", - coal->rx_max_coalesced_frames_high, - coal->rx_max_coalesced_frames_low, - COALESCE_PENDING_LIMIT_UNIT); - return -EOPNOTSUPP; - } - - if (coal->pkt_rate_low >= coal->pkt_rate_high) { - nicif_err(nic_dev, drv, netdev, "pkt_rate_high(%u) must more than pkt_rate_low(%u)\n", - coal->pkt_rate_high, - coal->pkt_rate_low); - return -EOPNOTSUPP; - } - - return 0; -} - -#define CHECK_COALESCE_ALIGN(coal, item, unit) \ -do { \ - if ((coal)->item % (unit)) \ - nicif_warn(nic_dev, drv, netdev, \ - "%s in %d units, change to %u\n", \ - #item, (unit), ((coal)->item - \ - (coal)->item % (unit))); \ -} while (0) - -#define CHECK_COALESCE_CHANGED(coal, item, unit, ori_val, obj_str) \ -do { \ - if (((coal)->item / (unit)) != (ori_val)) \ - nicif_info(nic_dev, drv, netdev, \ - "Change %s from %d to %u %s\n", \ - #item, (ori_val) * (unit), \ - ((coal)->item - (coal)->item % (unit)), \ - (obj_str)); \ -} while (0) - -#define CHECK_PKT_RATE_CHANGED(coal, item, ori_val, obj_str) \ -do { \ - if ((coal)->item != (ori_val)) \ - nicif_info(nic_dev, drv, netdev, \ - "Change %s from %llu to %u %s\n", \ - #item, (ori_val), (coal)->item, (obj_str)); \ -} while (0) - -static int set_hw_coal_param(struct spnic_nic_dev *nic_dev, struct spnic_intr_coal_info *intr_coal, - u16 queue) -{ - u16 i; - - if (queue == COALESCE_ALL_QUEUE) { - for (i = 0; i < nic_dev->max_qps; i++) - set_queue_coalesce(nic_dev, i, intr_coal); - } else { - if (queue >= nic_dev->q_params.num_qps) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Invalid queue_id: %u\n", queue); - return -EINVAL; - } - set_queue_coalesce(nic_dev, queue, intr_coal); - } - - return 0; -} - -static int set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal, u16 queue) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_intr_coal_info intr_coal = {0}; - struct spnic_intr_coal_info *ori_intr_coal = NULL; - u32 last_adaptive_rx; - char obj_str[32] = {0}; - int err = 0; - - err = is_coalesce_legal(netdev, coal); - if (err) - return err; - - CHECK_COALESCE_ALIGN(coal, rx_coalesce_usecs, COALESCE_TIMER_CFG_UNIT); - CHECK_COALESCE_ALIGN(coal, rx_max_coalesced_frames, COALESCE_PENDING_LIMIT_UNIT); - CHECK_COALESCE_ALIGN(coal, rx_coalesce_usecs_high, COALESCE_TIMER_CFG_UNIT); - CHECK_COALESCE_ALIGN(coal, rx_max_coalesced_frames_high, COALESCE_PENDING_LIMIT_UNIT); - CHECK_COALESCE_ALIGN(coal, rx_coalesce_usecs_low, COALESCE_TIMER_CFG_UNIT); - CHECK_COALESCE_ALIGN(coal, rx_max_coalesced_frames_low, COALESCE_PENDING_LIMIT_UNIT); - - if (queue == COALESCE_ALL_QUEUE) { - ori_intr_coal = &nic_dev->intr_coalesce[0]; - snprintf(obj_str, sizeof(obj_str), "for netdev"); - } else { - ori_intr_coal = &nic_dev->intr_coalesce[queue]; - snprintf(obj_str, sizeof(obj_str), "for queue %u", queue); - } - CHECK_COALESCE_CHANGED(coal, rx_coalesce_usecs, COALESCE_TIMER_CFG_UNIT, - ori_intr_coal->coalesce_timer_cfg, obj_str); - CHECK_COALESCE_CHANGED(coal, rx_max_coalesced_frames, COALESCE_PENDING_LIMIT_UNIT, - ori_intr_coal->pending_limt, obj_str); - CHECK_PKT_RATE_CHANGED(coal, pkt_rate_high, ori_intr_coal->pkt_rate_high, obj_str); - CHECK_COALESCE_CHANGED(coal, rx_coalesce_usecs_high, COALESCE_TIMER_CFG_UNIT, - ori_intr_coal->rx_usecs_high, obj_str); - CHECK_COALESCE_CHANGED(coal, rx_max_coalesced_frames_high, COALESCE_PENDING_LIMIT_UNIT, - ori_intr_coal->rx_pending_limt_high, obj_str); - CHECK_PKT_RATE_CHANGED(coal, pkt_rate_low, ori_intr_coal->pkt_rate_low, obj_str); - CHECK_COALESCE_CHANGED(coal, rx_coalesce_usecs_low, COALESCE_TIMER_CFG_UNIT, - ori_intr_coal->rx_usecs_low, obj_str); - CHECK_COALESCE_CHANGED(coal, rx_max_coalesced_frames_low, COALESCE_PENDING_LIMIT_UNIT, - ori_intr_coal->rx_pending_limt_low, obj_str); - - intr_coal.coalesce_timer_cfg = (u8)(coal->rx_coalesce_usecs / COALESCE_TIMER_CFG_UNIT); - intr_coal.pending_limt = (u8)(coal->rx_max_coalesced_frames / COALESCE_PENDING_LIMIT_UNIT); - - last_adaptive_rx = nic_dev->adaptive_rx_coal; - nic_dev->adaptive_rx_coal = coal->use_adaptive_rx_coalesce; - - intr_coal.pkt_rate_high = coal->pkt_rate_high; - intr_coal.rx_usecs_high = (u8)(coal->rx_coalesce_usecs_high / COALESCE_TIMER_CFG_UNIT); - intr_coal.rx_pending_limt_high = (u8)(coal->rx_max_coalesced_frames_high / - COALESCE_PENDING_LIMIT_UNIT); - - intr_coal.pkt_rate_low = coal->pkt_rate_low; - intr_coal.rx_usecs_low = (u8)(coal->rx_coalesce_usecs_low / COALESCE_TIMER_CFG_UNIT); - intr_coal.rx_pending_limt_low = (u8)(coal->rx_max_coalesced_frames_low / - COALESCE_PENDING_LIMIT_UNIT); - - /* coalesce timer or pending set to zero will disable coalesce */ - if (!nic_dev->adaptive_rx_coal && - (!intr_coal.coalesce_timer_cfg || !intr_coal.pending_limt)) - nicif_warn(nic_dev, drv, netdev, "Coalesce will be disabled\n"); - - /* ensure coalesce paramester will not be changed in auto - * moderation work - */ - if (SPHW_CHANNEL_RES_VALID(nic_dev)) { - if (!nic_dev->adaptive_rx_coal) - cancel_delayed_work_sync(&nic_dev->moderation_task); - else if (!last_adaptive_rx) - queue_delayed_work(nic_dev->workq, &nic_dev->moderation_task, - SPNIC_MODERATONE_DELAY); - } - - return set_hw_coal_param(nic_dev, &intr_coal, queue); -} - -static int spnic_get_coalesce(struct net_device *netdev, - struct ethtool_coalesce *coal, - struct kernel_ethtool_coalesce *kernel_coal, - struct netlink_ext_ack *ext_ack) -{ - return get_coalesce(netdev, coal, COALESCE_ALL_QUEUE); -} - -static int spnic_set_coalesce(struct net_device *netdev, - struct ethtool_coalesce *coal, - struct kernel_ethtool_coalesce *kernel_coal, - struct netlink_ext_ack *ext_ack) -{ - return set_coalesce(netdev, coal, COALESCE_ALL_QUEUE); -} - -static int spnic_get_per_queue_coalesce(struct net_device *netdev, u32 queue, - struct ethtool_coalesce *coal) -{ - return get_coalesce(netdev, coal, queue); -} - -static int spnic_set_per_queue_coalesce(struct net_device *netdev, u32 queue, - struct ethtool_coalesce *coal) -{ - return set_coalesce(netdev, coal, queue); -} - -static int spnic_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int err; - - switch (state) { - case ETHTOOL_ID_ACTIVE: - err = spnic_set_led_status(nic_dev->hwdev, MAG_CMD_LED_TYPE_ALARM, - MAG_CMD_LED_MODE_FORCE_BLINK_2HZ); - if (err) - nicif_err(nic_dev, drv, netdev, "Set LED blinking in 2HZ failed\n"); - else - nicif_info(nic_dev, drv, netdev, "Set LED blinking in 2HZ success\n"); - break; - - case ETHTOOL_ID_INACTIVE: - err = spnic_set_led_status(nic_dev->hwdev, MAG_CMD_LED_TYPE_ALARM, - MAG_CMD_LED_MODE_DEFAULT); - if (err) - nicif_err(nic_dev, drv, netdev, "Reset LED to original status failed\n"); - else - nicif_info(nic_dev, drv, netdev, "Reset LED to original status success\n"); - break; - - default: - return -EOPNOTSUPP; - } - - return err; -} - -static void spnic_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct nic_pause_config nic_pause = {0}; - int err; - - err = spnic_get_pause_info(nic_dev->hwdev, &nic_pause); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to get pauseparam from hw\n"); - } else { - pause->autoneg = nic_pause.auto_neg; - pause->rx_pause = nic_pause.rx_pause; - pause->tx_pause = nic_pause.tx_pause; - } -} - -static int spnic_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct nic_pause_config nic_pause = {0}; - struct nic_port_info port_info = {0}; - int err; - - err = spnic_get_port_info(nic_dev->hwdev, &port_info, SPHW_CHANNEL_NIC); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to get auto-negotiation state\n"); - return -EFAULT; - } - - if (pause->autoneg != port_info.autoneg_state) { - nicif_err(nic_dev, drv, netdev, "To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n"); - return -EOPNOTSUPP; - } - - if (nic_dev->hw_dcb_cfg.pfc_state) { - nicif_err(nic_dev, drv, netdev, "Can not set pause when pfc is enable\n"); - return -EPERM; - } - - nic_pause.auto_neg = (u8)pause->autoneg; - nic_pause.rx_pause = (u8)pause->rx_pause; - nic_pause.tx_pause = (u8)pause->tx_pause; - - err = spnic_set_pause_info(nic_dev->hwdev, nic_pause); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to set pauseparam\n"); - return -EFAULT; - } - - nicif_info(nic_dev, drv, netdev, "Set pause options, tx: %s, rx: %s\n", - pause->tx_pause ? "on" : "off", - pause->rx_pause ? "on" : "off"); - - return 0; -} - -static int spnic_get_module_info(struct net_device *netdev, struct ethtool_modinfo *modinfo) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u8 sfp_type = 0; - u8 sfp_type_ext = 0; - int err; - - err = spnic_get_sfp_type(nic_dev->hwdev, &sfp_type, &sfp_type_ext); - if (err) - return err; - - switch (sfp_type) { - case MODULE_TYPE_SFP: - modinfo->type = ETH_MODULE_SFF_8472; - modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; - break; - case MODULE_TYPE_QSFP: - modinfo->type = ETH_MODULE_SFF_8436; - modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN; - break; - case MODULE_TYPE_QSFP_PLUS: - if (sfp_type_ext >= 0x3) { - modinfo->type = ETH_MODULE_SFF_8636; - modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN; - - } else { - modinfo->type = ETH_MODULE_SFF_8436; - modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN; - } - break; - case MODULE_TYPE_QSFP28: - modinfo->type = ETH_MODULE_SFF_8636; - modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN; - break; - default: - nicif_warn(nic_dev, drv, netdev, "Optical module unknown: 0x%x\n", sfp_type); - return -EINVAL; - } - - return 0; -} - -static int spnic_get_module_eeprom(struct net_device *netdev, struct ethtool_eeprom *ee, u8 *data) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u8 sfp_data[STD_SFP_INFO_MAX_SIZE]; - int err; - - if (!ee->len || ((ee->len + ee->offset) > STD_SFP_INFO_MAX_SIZE)) - return -EINVAL; - - memset(data, 0, ee->len); - - err = spnic_get_sfp_eeprom(nic_dev->hwdev, (u8 *)sfp_data, ee->len); - if (err) - return err; - - memcpy(data, sfp_data + ee->offset, ee->len); - - return 0; -} - -#define SPNIC_PRIV_FLAGS_SYMM_RSS BIT(0) - -static u32 spnic_get_priv_flags(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u32 priv_flags = 0; - - if (test_bit(SPNIC_SAME_RXTX, &nic_dev->flags)) - priv_flags |= SPNIC_PRIV_FLAGS_SYMM_RSS; - - return priv_flags; -} - -static int spnic_set_priv_flags(struct net_device *netdev, u32 priv_flags) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - if (priv_flags & SPNIC_PRIV_FLAGS_SYMM_RSS) { - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - nicif_err(nic_dev, drv, netdev, "Failed to open Symmetric RSS while DCB is enabled\n"); - return -EOPNOTSUPP; - } - set_bit(SPNIC_SAME_RXTX, &nic_dev->flags); - } else { - clear_bit(SPNIC_SAME_RXTX, &nic_dev->flags); - } - - return 0; -} - -#define BROADCAST_PACKET_SIM 0xFF -#define UNICAST_PACKET_SIM 0xFE -#define IP_PROTOCOL_TYPE 0x08 -#define IP_PROTOCOL_COMPLEMENT 0x00 - -#define PORT_DOWN_ERR_IDX 0 -#define LP_DEFAULT_TIME 5 /* seconds */ -#define LP_PKT_LEN 1514 - -#define TEST_TIME_MULTIPLE 5 -static int spnic_run_lp_test(struct spnic_nic_dev *nic_dev, u32 test_time) -{ - u32 cnt = test_time * TEST_TIME_MULTIPLE; - struct sk_buff *skb = NULL; - struct sk_buff *skb_tmp = NULL; - u8 *test_data = NULL; - u8 *lb_test_rx_buf = nic_dev->lb_test_rx_buf; - struct net_device *netdev = nic_dev->netdev; - u32 i; - u8 j; - - skb_tmp = alloc_skb(LP_PKT_LEN, GFP_ATOMIC); - if (!skb_tmp) { - nicif_err(nic_dev, drv, netdev, "Alloc xmit skb template failed for loopback test\n"); - return -ENOMEM; - } - - test_data = __skb_put(skb_tmp, LP_PKT_LEN); - - memset(test_data, BROADCAST_PACKET_SIM, ETH_ALEN + ETH_ALEN); - - test_data[ETH_ALEN] = UNICAST_PACKET_SIM; - test_data[ETH_ALEN + ETH_ALEN] = IP_PROTOCOL_TYPE; - test_data[ETH_ALEN + ETH_ALEN + 1] = IP_PROTOCOL_COMPLEMENT; - - for (i = ETH_HLEN; i < LP_PKT_LEN; i++) - test_data[i] = i & 0xFF; - - skb_tmp->queue_mapping = 0; - skb_tmp->ip_summed = CHECKSUM_COMPLETE; - skb_tmp->dev = netdev; - - for (i = 0; i < cnt; i++) { - nic_dev->lb_test_rx_idx = 0; - memset(lb_test_rx_buf, 0, LP_PKT_CNT * LP_PKT_LEN); - - for (j = 0; j < LP_PKT_CNT; j++) { - skb = pskb_copy(skb_tmp, GFP_ATOMIC); - if (!skb) { - dev_kfree_skb_any(skb_tmp); - nicif_err(nic_dev, drv, netdev, "Copy skb failed for loopback test\n"); - return -ENOMEM; - } - - /* mark index for every pkt */ - skb->data[LP_PKT_LEN - 1] = j; - - if (spnic_lb_xmit_frame(skb, netdev)) { - dev_kfree_skb_any(skb); - dev_kfree_skb_any(skb_tmp); - nicif_err(nic_dev, drv, netdev, "Xmit pkt failed for loopback test\n"); - return -EBUSY; - } - } - - /* wait till all pkts received to RX buffer */ - msleep(200); - - for (j = 0; j < LP_PKT_CNT; j++) { - if (memcmp((lb_test_rx_buf + (j * LP_PKT_LEN)), - skb_tmp->data, (LP_PKT_LEN - 1)) || - (*(lb_test_rx_buf + ((j * LP_PKT_LEN) + - (LP_PKT_LEN - 1))) != j)) { - dev_kfree_skb_any(skb_tmp); - nicif_err(nic_dev, drv, netdev, - "Compare pkt failed in loopback test(index=0x%02x, data[%d]=0x%02x)\n", - (j + (i * LP_PKT_CNT)), (LP_PKT_LEN - 1), - *(lb_test_rx_buf + - ((j * LP_PKT_LEN) + (LP_PKT_LEN - 1)))); - return -EIO; - } - } - } - - dev_kfree_skb_any(skb_tmp); - nicif_info(nic_dev, drv, netdev, "Loopback test succeed.\n"); - return 0; -} - -enum diag_test_index { - INTERNAL_LP_TEST = 0, - EXTERNAL_LP_TEST = 1, - DIAG_TEST_MAX = 2, -}; - -#define SPNIC_INTERNAL_LP_MODE 5 -static int do_lp_test(struct spnic_nic_dev *nic_dev, u32 *flags, u32 test_time, - enum diag_test_index *test_index) -{ - struct net_device *netdev = nic_dev->netdev; - u8 *lb_test_rx_buf = NULL; - int err = 0; - - if (!(*flags & ETH_TEST_FL_EXTERNAL_LB)) { - *test_index = INTERNAL_LP_TEST; - if (spnic_set_loopback_mode(nic_dev->hwdev, SPNIC_INTERNAL_LP_MODE, true)) { - nicif_err(nic_dev, drv, netdev, - "Failed to set port loopback mode before loopback test\n"); - return -EFAULT; - } - } else { - *test_index = EXTERNAL_LP_TEST; - } - - lb_test_rx_buf = vmalloc(LP_PKT_CNT * LP_PKT_LEN); - if (!lb_test_rx_buf) { - nicif_err(nic_dev, drv, netdev, "Failed to alloc RX buffer for loopback test\n"); - err = -ENOMEM; - } else { - nic_dev->lb_test_rx_buf = lb_test_rx_buf; - nic_dev->lb_pkt_len = LP_PKT_LEN; - set_bit(SPNIC_LP_TEST, &nic_dev->flags); - - if (spnic_run_lp_test(nic_dev, test_time)) - err = -EFAULT; - - clear_bit(SPNIC_LP_TEST, &nic_dev->flags); - msleep(100); - vfree(lb_test_rx_buf); - nic_dev->lb_test_rx_buf = NULL; - } - - if (!(*flags & ETH_TEST_FL_EXTERNAL_LB)) { - if (spnic_set_loopback_mode(nic_dev->hwdev, SPNIC_INTERNAL_LP_MODE, false)) { - nicif_err(nic_dev, drv, netdev, - "Failed to cancel port loopback mode after loopback test\n"); - err = -EFAULT; - } - } else { - *flags |= ETH_TEST_FL_EXTERNAL_LB_DONE; - } - - return err; -} - -void spnic_lp_test(struct net_device *netdev, struct ethtool_test *eth_test, - u64 *data, u32 test_time) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - enum diag_test_index test_index = 0; - u8 link_status = 0; - int err; - - /* don't support loopback test when netdev is closed. */ - if (!test_bit(SPNIC_INTF_UP, &nic_dev->flags)) { - nicif_err(nic_dev, drv, netdev, - "Do not support loopback test when netdev is closed\n"); - eth_test->flags |= ETH_TEST_FL_FAILED; - data[PORT_DOWN_ERR_IDX] = 1; - return; - } - - if (test_time == 0) - test_time = LP_DEFAULT_TIME; - - netif_carrier_off(netdev); - netif_tx_disable(netdev); - - err = do_lp_test(nic_dev, ð_test->flags, test_time, &test_index); - if (err) { - eth_test->flags |= ETH_TEST_FL_FAILED; - data[test_index] = 1; - } - - netif_tx_wake_all_queues(netdev); - - err = spnic_get_link_state(nic_dev->hwdev, &link_status); - if (!err && link_status) - netif_carrier_on(netdev); -} - -static void spnic_diag_test(struct net_device *netdev, struct ethtool_test *eth_test, u64 *data) -{ - memset(data, 0, DIAG_TEST_MAX * sizeof(u64)); - - spnic_lp_test(netdev, eth_test, data, 0); -} - -static const struct ethtool_ops spnic_ethtool_ops = { - .supported_coalesce_params = ETHTOOL_COALESCE_USECS | - ETHTOOL_COALESCE_PKT_RATE_RX_USECS, - .get_link_ksettings = spnic_get_link_ksettings, - .set_link_ksettings = spnic_set_link_ksettings, - - .get_drvinfo = spnic_get_drvinfo, - .get_msglevel = spnic_get_msglevel, - .set_msglevel = spnic_set_msglevel, - .nway_reset = spnic_nway_reset, - .get_link = ethtool_op_get_link, - .get_ringparam = spnic_get_ringparam, - .set_ringparam = spnic_set_ringparam, - .get_pauseparam = spnic_get_pauseparam, - .set_pauseparam = spnic_set_pauseparam, - .get_sset_count = spnic_get_sset_count, - .get_ethtool_stats = spnic_get_ethtool_stats, - .get_strings = spnic_get_strings, - - .self_test = spnic_diag_test, - .set_phys_id = spnic_set_phys_id, - - .get_coalesce = spnic_get_coalesce, - .set_coalesce = spnic_set_coalesce, - .get_per_queue_coalesce = spnic_get_per_queue_coalesce, - .set_per_queue_coalesce = spnic_set_per_queue_coalesce, - - .get_rxnfc = spnic_get_rxnfc, - .set_rxnfc = spnic_set_rxnfc, - .get_priv_flags = spnic_get_priv_flags, - .set_priv_flags = spnic_set_priv_flags, - - .get_channels = spnic_get_channels, - .set_channels = spnic_set_channels, - - .get_module_info = spnic_get_module_info, - .get_module_eeprom = spnic_get_module_eeprom, - - .get_rxfh_indir_size = spnic_get_rxfh_indir_size, - .get_rxfh_key_size = spnic_get_rxfh_key_size, - .get_rxfh = spnic_get_rxfh, - .set_rxfh = spnic_set_rxfh, -}; - -static const struct ethtool_ops spnicvf_ethtool_ops = { - .supported_coalesce_params = ETHTOOL_COALESCE_USECS | - ETHTOOL_COALESCE_PKT_RATE_RX_USECS, - .get_link_ksettings = spnic_get_link_ksettings, - .get_drvinfo = spnic_get_drvinfo, - .get_msglevel = spnic_get_msglevel, - .set_msglevel = spnic_set_msglevel, - .get_link = ethtool_op_get_link, - .get_ringparam = spnic_get_ringparam, - - .set_ringparam = spnic_set_ringparam, - .get_sset_count = spnic_get_sset_count, - .get_ethtool_stats = spnic_get_ethtool_stats, - .get_strings = spnic_get_strings, - - .get_coalesce = spnic_get_coalesce, - .set_coalesce = spnic_set_coalesce, - .get_per_queue_coalesce = spnic_get_per_queue_coalesce, - .set_per_queue_coalesce = spnic_set_per_queue_coalesce, - - .get_rxnfc = spnic_get_rxnfc, - .set_rxnfc = spnic_set_rxnfc, - .get_priv_flags = spnic_get_priv_flags, - .set_priv_flags = spnic_set_priv_flags, - - .get_channels = spnic_get_channels, - .set_channels = spnic_set_channels, - - .get_rxfh_indir_size = spnic_get_rxfh_indir_size, - .get_rxfh_key_size = spnic_get_rxfh_key_size, - .get_rxfh = spnic_get_rxfh, - .set_rxfh = spnic_set_rxfh, -}; - -void spnic_set_ethtool_ops(struct net_device *netdev) -{ - netdev->ethtool_ops = &spnic_ethtool_ops; -} - -void spnicvf_set_ethtool_ops(struct net_device *netdev) -{ - netdev->ethtool_ops = &spnicvf_ethtool_ops; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_ethtool_stats.c b/drivers/net/ethernet/ramaxel/spnic/spnic_ethtool_stats.c deleted file mode 100644 index 5a830e3454d4..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_ethtool_stats.c +++ /dev/null @@ -1,1035 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/if_vlan.h> -#include <linux/ethtool.h> - -#include "sphw_hw.h" -#include "sphw_crm.h" -#include "sphw_mt.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic_dev.h" -#include "spnic_tx.h" -#include "spnic_rx.h" - -struct spnic_stats { - char name[ETH_GSTRING_LEN]; - u32 size; - int offset; -}; - -#define SPNIC_NETDEV_STAT(_stat_item) { \ - .name = #_stat_item, \ - .size = sizeof_field(struct rtnl_link_stats64, _stat_item), \ - .offset = offsetof(struct rtnl_link_stats64, _stat_item) \ -} - -static struct spnic_stats spnic_netdev_stats[] = { - SPNIC_NETDEV_STAT(rx_packets), - SPNIC_NETDEV_STAT(tx_packets), - SPNIC_NETDEV_STAT(rx_bytes), - SPNIC_NETDEV_STAT(tx_bytes), - SPNIC_NETDEV_STAT(rx_errors), - SPNIC_NETDEV_STAT(tx_errors), - SPNIC_NETDEV_STAT(rx_dropped), - SPNIC_NETDEV_STAT(tx_dropped), - SPNIC_NETDEV_STAT(multicast), - SPNIC_NETDEV_STAT(collisions), - SPNIC_NETDEV_STAT(rx_length_errors), - SPNIC_NETDEV_STAT(rx_over_errors), - SPNIC_NETDEV_STAT(rx_crc_errors), - SPNIC_NETDEV_STAT(rx_frame_errors), - SPNIC_NETDEV_STAT(rx_fifo_errors), - SPNIC_NETDEV_STAT(rx_missed_errors), - SPNIC_NETDEV_STAT(tx_aborted_errors), - SPNIC_NETDEV_STAT(tx_carrier_errors), - SPNIC_NETDEV_STAT(tx_fifo_errors), - SPNIC_NETDEV_STAT(tx_heartbeat_errors), -}; - -#define SPNIC_NIC_STAT(_stat_item) { \ - .name = #_stat_item, \ - .size = sizeof_field(struct spnic_nic_stats, _stat_item), \ - .offset = offsetof(struct spnic_nic_stats, _stat_item) \ -} - -static struct spnic_stats spnic_nic_dev_stats[] = { - SPNIC_NIC_STAT(netdev_tx_timeout), -}; - -static struct spnic_stats spnic_nic_dev_stats_extern[] = { - SPNIC_NIC_STAT(tx_carrier_off_drop), - SPNIC_NIC_STAT(tx_invalid_qid), -}; - -#define SPNIC_RXQ_STAT(_stat_item) { \ - .name = "rxq%d_"#_stat_item, \ - .size = sizeof_field(struct spnic_rxq_stats, _stat_item), \ - .offset = offsetof(struct spnic_rxq_stats, _stat_item) \ -} - -#define SPNIC_TXQ_STAT(_stat_item) { \ - .name = "txq%d_"#_stat_item, \ - .size = sizeof_field(struct spnic_txq_stats, _stat_item), \ - .offset = offsetof(struct spnic_txq_stats, _stat_item) \ -} - -static struct spnic_stats spnic_rx_queue_stats[] = { - SPNIC_RXQ_STAT(packets), - SPNIC_RXQ_STAT(bytes), - SPNIC_RXQ_STAT(errors), - SPNIC_RXQ_STAT(csum_errors), - SPNIC_RXQ_STAT(other_errors), - SPNIC_RXQ_STAT(dropped), - SPNIC_RXQ_STAT(xdp_dropped), - SPNIC_RXQ_STAT(rx_buf_empty), -}; - -static struct spnic_stats spnic_rx_queue_stats_extern[] = { - SPNIC_RXQ_STAT(alloc_skb_err), - SPNIC_RXQ_STAT(alloc_rx_buf_err), - SPNIC_RXQ_STAT(xdp_large_pkt), -}; - -static struct spnic_stats spnic_tx_queue_stats[] = { - SPNIC_TXQ_STAT(packets), - SPNIC_TXQ_STAT(bytes), - SPNIC_TXQ_STAT(busy), - SPNIC_TXQ_STAT(wake), - SPNIC_TXQ_STAT(dropped), -}; - -static struct spnic_stats spnic_tx_queue_stats_extern[] = { - SPNIC_TXQ_STAT(skb_pad_err), - SPNIC_TXQ_STAT(frag_len_overflow), - SPNIC_TXQ_STAT(offload_cow_skb_err), - SPNIC_TXQ_STAT(map_frag_err), - SPNIC_TXQ_STAT(unknown_tunnel_pkt), - SPNIC_TXQ_STAT(frag_size_err), -}; - -#define SPNIC_FUNC_STAT(_stat_item) { \ - .name = #_stat_item, \ - .size = sizeof_field(struct spnic_vport_stats, _stat_item), \ - .offset = offsetof(struct spnic_vport_stats, _stat_item) \ -} - -static struct spnic_stats spnic_function_stats[] = { - SPNIC_FUNC_STAT(tx_unicast_pkts_vport), - SPNIC_FUNC_STAT(tx_unicast_bytes_vport), - SPNIC_FUNC_STAT(tx_multicast_pkts_vport), - SPNIC_FUNC_STAT(tx_multicast_bytes_vport), - SPNIC_FUNC_STAT(tx_broadcast_pkts_vport), - SPNIC_FUNC_STAT(tx_broadcast_bytes_vport), - - SPNIC_FUNC_STAT(rx_unicast_pkts_vport), - SPNIC_FUNC_STAT(rx_unicast_bytes_vport), - SPNIC_FUNC_STAT(rx_multicast_pkts_vport), - SPNIC_FUNC_STAT(rx_multicast_bytes_vport), - SPNIC_FUNC_STAT(rx_broadcast_pkts_vport), - SPNIC_FUNC_STAT(rx_broadcast_bytes_vport), - - SPNIC_FUNC_STAT(tx_discard_vport), - SPNIC_FUNC_STAT(rx_discard_vport), - SPNIC_FUNC_STAT(tx_err_vport), - SPNIC_FUNC_STAT(rx_err_vport), -}; - -#define SPNIC_PORT_STAT(_stat_item) { \ - .name = #_stat_item, \ - .size = sizeof_field(struct mag_cmd_port_stats, _stat_item), \ - .offset = offsetof(struct mag_cmd_port_stats, _stat_item) \ -} - -static struct spnic_stats spnic_port_stats[] = { - SPNIC_PORT_STAT(mac_rx_total_pkt_num), - SPNIC_PORT_STAT(mac_rx_total_oct_num), - SPNIC_PORT_STAT(mac_rx_bad_pkt_num), - SPNIC_PORT_STAT(mac_rx_bad_oct_num), - SPNIC_PORT_STAT(mac_rx_good_pkt_num), - SPNIC_PORT_STAT(mac_rx_good_oct_num), - SPNIC_PORT_STAT(mac_rx_uni_pkt_num), - SPNIC_PORT_STAT(mac_rx_multi_pkt_num), - SPNIC_PORT_STAT(mac_rx_broad_pkt_num), - SPNIC_PORT_STAT(mac_tx_total_pkt_num), - SPNIC_PORT_STAT(mac_tx_total_oct_num), - SPNIC_PORT_STAT(mac_tx_bad_pkt_num), - SPNIC_PORT_STAT(mac_tx_bad_oct_num), - SPNIC_PORT_STAT(mac_tx_good_pkt_num), - SPNIC_PORT_STAT(mac_tx_good_oct_num), - SPNIC_PORT_STAT(mac_tx_uni_pkt_num), - SPNIC_PORT_STAT(mac_tx_multi_pkt_num), - SPNIC_PORT_STAT(mac_tx_broad_pkt_num), - SPNIC_PORT_STAT(mac_rx_fragment_pkt_num), - SPNIC_PORT_STAT(mac_rx_undersize_pkt_num), - SPNIC_PORT_STAT(mac_rx_undermin_pkt_num), - SPNIC_PORT_STAT(mac_rx_64_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_65_127_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_128_255_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_256_511_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_512_1023_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_1024_1518_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_1519_2047_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_2048_4095_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_4096_8191_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_8192_9216_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_9217_12287_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_12288_16383_oct_pkt_num), - SPNIC_PORT_STAT(mac_rx_1519_max_good_pkt_num), - SPNIC_PORT_STAT(mac_rx_1519_max_bad_pkt_num), - SPNIC_PORT_STAT(mac_rx_oversize_pkt_num), - SPNIC_PORT_STAT(mac_rx_jabber_pkt_num), - SPNIC_PORT_STAT(mac_rx_pause_num), - SPNIC_PORT_STAT(mac_rx_pfc_pkt_num), - SPNIC_PORT_STAT(mac_rx_pfc_pri0_pkt_num), - SPNIC_PORT_STAT(mac_rx_pfc_pri1_pkt_num), - SPNIC_PORT_STAT(mac_rx_pfc_pri2_pkt_num), - SPNIC_PORT_STAT(mac_rx_pfc_pri3_pkt_num), - SPNIC_PORT_STAT(mac_rx_pfc_pri4_pkt_num), - SPNIC_PORT_STAT(mac_rx_pfc_pri5_pkt_num), - SPNIC_PORT_STAT(mac_rx_pfc_pri6_pkt_num), - SPNIC_PORT_STAT(mac_rx_pfc_pri7_pkt_num), - SPNIC_PORT_STAT(mac_rx_control_pkt_num), - SPNIC_PORT_STAT(mac_rx_sym_err_pkt_num), - SPNIC_PORT_STAT(mac_rx_fcs_err_pkt_num), - SPNIC_PORT_STAT(mac_rx_send_app_good_pkt_num), - SPNIC_PORT_STAT(mac_rx_send_app_bad_pkt_num), - SPNIC_PORT_STAT(mac_tx_fragment_pkt_num), - SPNIC_PORT_STAT(mac_tx_undersize_pkt_num), - SPNIC_PORT_STAT(mac_tx_undermin_pkt_num), - SPNIC_PORT_STAT(mac_tx_64_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_65_127_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_128_255_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_256_511_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_512_1023_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_1024_1518_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_1519_2047_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_2048_4095_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_4096_8191_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_8192_9216_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_9217_12287_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_12288_16383_oct_pkt_num), - SPNIC_PORT_STAT(mac_tx_1519_max_good_pkt_num), - SPNIC_PORT_STAT(mac_tx_1519_max_bad_pkt_num), - SPNIC_PORT_STAT(mac_tx_oversize_pkt_num), - SPNIC_PORT_STAT(mac_tx_jabber_pkt_num), - SPNIC_PORT_STAT(mac_tx_pause_num), - SPNIC_PORT_STAT(mac_tx_pfc_pkt_num), - SPNIC_PORT_STAT(mac_tx_pfc_pri0_pkt_num), - SPNIC_PORT_STAT(mac_tx_pfc_pri1_pkt_num), - SPNIC_PORT_STAT(mac_tx_pfc_pri2_pkt_num), - SPNIC_PORT_STAT(mac_tx_pfc_pri3_pkt_num), - SPNIC_PORT_STAT(mac_tx_pfc_pri4_pkt_num), - SPNIC_PORT_STAT(mac_tx_pfc_pri5_pkt_num), - SPNIC_PORT_STAT(mac_tx_pfc_pri6_pkt_num), - SPNIC_PORT_STAT(mac_tx_pfc_pri7_pkt_num), - SPNIC_PORT_STAT(mac_tx_control_pkt_num), - SPNIC_PORT_STAT(mac_tx_err_all_pkt_num), - SPNIC_PORT_STAT(mac_tx_from_app_good_pkt_num), - SPNIC_PORT_STAT(mac_tx_from_app_bad_pkt_num), -}; - -static char g_spnic_priv_flags_strings[][ETH_GSTRING_LEN] = { - "Symmetric-RSS", -}; - -u32 spnic_get_io_stats_size(struct spnic_nic_dev *nic_dev) -{ - u32 count; - - count = ARRAY_LEN(spnic_nic_dev_stats) + - ARRAY_LEN(spnic_nic_dev_stats_extern) + - (ARRAY_LEN(spnic_tx_queue_stats) + - ARRAY_LEN(spnic_tx_queue_stats_extern) + - ARRAY_LEN(spnic_rx_queue_stats) + - ARRAY_LEN(spnic_rx_queue_stats_extern)) * nic_dev->max_qps; - - return count; -} - -#define GET_VALUE_OF_PTR(size, ptr) ( \ - (size) == sizeof(u64) ? *(u64 *)(ptr) : \ - (size) == sizeof(u32) ? *(u32 *)(ptr) : \ - (size) == sizeof(u16) ? *(u16 *)(ptr) : *(u8 *)(ptr) \ -) - -#define DEV_STATS_PACK(items, item_idx, array, stats_ptr) do { \ - int j; \ - for (j = 0; j < ARRAY_LEN(array); j++) { \ - memcpy((items)[item_idx].name, (array)[j].name, \ - SPNIC_SHOW_ITEM_LEN); \ - (items)[item_idx].hexadecimal = 0; \ - (items)[item_idx].value = \ - GET_VALUE_OF_PTR((array)[j].size, \ - (char *)(stats_ptr) + (array)[j].offset); \ - (item_idx)++; \ - } \ -} while (0) - -#define QUEUE_STATS_PACK(items, item_idx, array, stats_ptr, qid) do { \ - int j; \ - for (j = 0; j < ARRAY_LEN(array); j++) { \ - memcpy((items)[item_idx].name, (array)[j].name, \ - SPNIC_SHOW_ITEM_LEN); \ - snprintf((items)[item_idx].name, SPNIC_SHOW_ITEM_LEN, \ - (array)[j].name, (qid)); \ - (items)[item_idx].hexadecimal = 0; \ - (items)[item_idx].value = \ - GET_VALUE_OF_PTR((array)[j].size, \ - (char *)(stats_ptr) + (array)[j].offset); \ - (item_idx)++; \ - } \ -} while (0) - -void spnic_get_io_stats(struct spnic_nic_dev *nic_dev, void *stats) -{ - struct spnic_show_item *items = stats; - int item_idx = 0; - u16 qid; - - DEV_STATS_PACK(items, item_idx, spnic_nic_dev_stats, &nic_dev->stats); - DEV_STATS_PACK(items, item_idx, spnic_nic_dev_stats_extern, - &nic_dev->stats); - - for (qid = 0; qid < nic_dev->max_qps; qid++) { - QUEUE_STATS_PACK(items, item_idx, spnic_tx_queue_stats, - &nic_dev->txqs[qid].txq_stats, qid); - QUEUE_STATS_PACK(items, item_idx, spnic_tx_queue_stats_extern, - &nic_dev->txqs[qid].txq_stats, qid); - } - - for (qid = 0; qid < nic_dev->max_qps; qid++) { - QUEUE_STATS_PACK(items, item_idx, spnic_rx_queue_stats, - &nic_dev->rxqs[qid].rxq_stats, qid); - QUEUE_STATS_PACK(items, item_idx, spnic_rx_queue_stats_extern, - &nic_dev->rxqs[qid].rxq_stats, qid); - } -} - -static char spnic_test_strings[][ETH_GSTRING_LEN] = { - "Internal lb test (on/offline)", - "External lb test (external_lb)", -}; - -int spnic_get_sset_count(struct net_device *netdev, int sset) -{ - int count = 0, q_num = 0; - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - switch (sset) { - case ETH_SS_TEST: - return ARRAY_LEN(spnic_test_strings); - case ETH_SS_STATS: - q_num = nic_dev->q_params.num_qps; - count = ARRAY_LEN(spnic_netdev_stats) + - ARRAY_LEN(spnic_nic_dev_stats) + - ARRAY_LEN(spnic_function_stats) + - (ARRAY_LEN(spnic_tx_queue_stats) + - ARRAY_LEN(spnic_rx_queue_stats)) * q_num; - - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) - count += ARRAY_LEN(spnic_port_stats); - - return count; - case ETH_SS_PRIV_FLAGS: - return ARRAY_LEN(g_spnic_priv_flags_strings); - default: - return -EOPNOTSUPP; - } -} - -static void get_drv_queue_stats(struct spnic_nic_dev *nic_dev, u64 *data) -{ - struct spnic_txq_stats txq_stats; - struct spnic_rxq_stats rxq_stats; - u16 i = 0, j = 0, qid = 0; - char *p = NULL; - - for (qid = 0; qid < nic_dev->q_params.num_qps; qid++) { - if (!nic_dev->txqs) - break; - - spnic_txq_get_stats(&nic_dev->txqs[qid], &txq_stats); - for (j = 0; j < ARRAY_LEN(spnic_tx_queue_stats); j++, i++) { - p = (char *)(&txq_stats) + - spnic_tx_queue_stats[j].offset; - data[i] = (spnic_tx_queue_stats[j].size == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; - } - } - - for (qid = 0; qid < nic_dev->q_params.num_qps; qid++) { - if (!nic_dev->rxqs) - break; - - spnic_rxq_get_stats(&nic_dev->rxqs[qid], &rxq_stats); - for (j = 0; j < ARRAY_LEN(spnic_rx_queue_stats); j++, i++) { - p = (char *)(&rxq_stats) + - spnic_rx_queue_stats[j].offset; - data[i] = (spnic_rx_queue_stats[j].size == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; - } - } -} - -static u16 get_ethtool_port_stats(struct spnic_nic_dev *nic_dev, u64 *data) -{ - struct mag_cmd_port_stats *port_stats; - char *p = NULL; - u16 i = 0, j = 0; - int err; - - port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL); - if (!port_stats) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to malloc port stats\n"); - memset(&data[i], 0, - ARRAY_LEN(spnic_port_stats) * sizeof(*data)); - i += ARRAY_LEN(spnic_port_stats); - return i; - } - - err = spnic_get_phy_port_stats(nic_dev->hwdev, port_stats); - if (err) - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to get port stats from fw\n"); - - for (j = 0; j < ARRAY_LEN(spnic_port_stats); j++, i++) { - p = (char *)(port_stats) + spnic_port_stats[j].offset; - data[i] = (spnic_port_stats[j].size == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; - } - - kfree(port_stats); - - return i; -} - -void spnic_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, u64 *data) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct rtnl_link_stats64 temp; - const struct rtnl_link_stats64 *net_stats = NULL; - struct spnic_nic_stats *nic_stats = NULL; - - struct spnic_vport_stats vport_stats = {0}; - u16 i = 0, j = 0; - char *p = NULL; - int err; - - net_stats = dev_get_stats(netdev, &temp); - for (j = 0; j < ARRAY_LEN(spnic_netdev_stats); j++, i++) { - p = (char *)(net_stats) + spnic_netdev_stats[j].offset; - data[i] = GET_VALUE_OF_PTR(spnic_netdev_stats[j].size, p); - } - - nic_stats = &nic_dev->stats; - for (j = 0; j < ARRAY_LEN(spnic_nic_dev_stats); j++, i++) { - p = (char *)(nic_stats) + spnic_nic_dev_stats[j].offset; - data[i] = GET_VALUE_OF_PTR(spnic_nic_dev_stats[j].size, p); - } - - err = spnic_get_vport_stats(nic_dev->hwdev, &vport_stats); - if (err) - nicif_err(nic_dev, drv, netdev, - "Failed to get function stats from fw\n"); - - for (j = 0; j < ARRAY_LEN(spnic_function_stats); j++, i++) { - p = (char *)(&vport_stats) + spnic_function_stats[j].offset; - data[i] = GET_VALUE_OF_PTR(spnic_function_stats[j].size, p); - } - - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) - i += get_ethtool_port_stats(nic_dev, data + i); - - get_drv_queue_stats(nic_dev, data + i); -} - -static u16 get_drv_dev_strings(struct spnic_nic_dev *nic_dev, char *p) -{ - u16 i, cnt = 0; - - for (i = 0; i < ARRAY_LEN(spnic_netdev_stats); i++) { - memcpy(p, spnic_netdev_stats[i].name, - ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - cnt++; - } - - for (i = 0; i < ARRAY_LEN(spnic_nic_dev_stats); i++) { - memcpy(p, spnic_nic_dev_stats[i].name, ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - cnt++; - } - - return cnt; -} - -static u16 get_hw_stats_strings(struct spnic_nic_dev *nic_dev, char *p) -{ - u16 i, cnt = 0; - - for (i = 0; i < ARRAY_LEN(spnic_function_stats); i++) { - memcpy(p, spnic_function_stats[i].name, - ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - cnt++; - } - - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) { - for (i = 0; i < ARRAY_LEN(spnic_port_stats); i++) { - memcpy(p, spnic_port_stats[i].name, - ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - cnt++; - } - } - - return cnt; -} - -static u16 get_qp_stats_strings(struct spnic_nic_dev *nic_dev, char *p) -{ - u16 i = 0, j = 0, cnt = 0; - - for (i = 0; i < nic_dev->q_params.num_qps; i++) { - for (j = 0; j < ARRAY_LEN(spnic_tx_queue_stats); j++) { - sprintf(p, spnic_tx_queue_stats[j].name, i); - p += ETH_GSTRING_LEN; - cnt++; - } - } - - for (i = 0; i < nic_dev->q_params.num_qps; i++) { - for (j = 0; j < ARRAY_LEN(spnic_rx_queue_stats); j++) { - sprintf(p, spnic_rx_queue_stats[j].name, i); - p += ETH_GSTRING_LEN; - cnt++; - } - } - - return cnt; -} - -void spnic_get_strings(struct net_device *netdev, u32 stringset, u8 *data) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - char *p = (char *)data; - u16 offset = 0; - - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *spnic_test_strings, sizeof(spnic_test_strings)); - return; - case ETH_SS_STATS: - offset = get_drv_dev_strings(nic_dev, p); - offset += get_hw_stats_strings(nic_dev, - p + offset * ETH_GSTRING_LEN); - get_qp_stats_strings(nic_dev, p + offset * ETH_GSTRING_LEN); - - return; - case ETH_SS_PRIV_FLAGS: - memcpy(data, g_spnic_priv_flags_strings, - sizeof(g_spnic_priv_flags_strings)); - return; - default: - nicif_err(nic_dev, drv, netdev, - "Invalid string set %u.", stringset); - return; - } -} - -static const u32 spnic_mag_link_mode_ge[] = { - ETHTOOL_LINK_MODE_1000baseT_Full_BIT, - ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, - ETHTOOL_LINK_MODE_1000baseX_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_10ge_base_r[] = { - ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, - ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, - ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, - ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, - ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, - ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_25ge_base_r[] = { - ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, - ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, - ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_40ge_base_r4[] = { - ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, - ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, - ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, - ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_50ge_base_r[] = { - ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, - ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, - ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_50ge_base_r2[] = { - ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, - ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, - ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_100ge_base_r[] = { - ETHTOOL_LINK_MODE_100000baseKR_Full_BIT, - ETHTOOL_LINK_MODE_100000baseSR_Full_BIT, - ETHTOOL_LINK_MODE_100000baseCR_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_100ge_base_r2[] = { - ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT, - ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, - ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_100ge_base_r4[] = { - ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, - ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, - ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_200ge_base_r2[] = { - ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT, - ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT, - ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT, -}; - -static const u32 spnic_mag_link_mode_200ge_base_r4[] = { - ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT, - ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT, - ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT, -}; - -struct hw2ethtool_link_mode { - const u32 *link_mode_bit_arr; - u32 arr_size; - u32 speed; -}; - -static const struct hw2ethtool_link_mode - hw2ethtool_link_mode_table[LINK_MODE_MAX_NUMBERS] = { - [LINK_MODE_GE] = { - .link_mode_bit_arr = spnic_mag_link_mode_ge, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_ge), - .speed = SPEED_1000, - }, - [LINK_MODE_10GE_BASE_R] = { - .link_mode_bit_arr = spnic_mag_link_mode_10ge_base_r, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_10ge_base_r), - .speed = SPEED_10000, - }, - [LINK_MODE_25GE_BASE_R] = { - .link_mode_bit_arr = spnic_mag_link_mode_25ge_base_r, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_25ge_base_r), - .speed = SPEED_25000, - }, - [LINK_MODE_40GE_BASE_R4] = { - .link_mode_bit_arr = spnic_mag_link_mode_40ge_base_r4, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_40ge_base_r4), - .speed = SPEED_40000, - }, - [LINK_MODE_50GE_BASE_R] = { - .link_mode_bit_arr = spnic_mag_link_mode_50ge_base_r, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_50ge_base_r), - .speed = SPEED_50000, - }, - [LINK_MODE_50GE_BASE_R2] = { - .link_mode_bit_arr = spnic_mag_link_mode_50ge_base_r2, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_50ge_base_r2), - .speed = SPEED_50000, - }, - [LINK_MODE_100GE_BASE_R] = { - .link_mode_bit_arr = spnic_mag_link_mode_100ge_base_r, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_100ge_base_r), - .speed = SPEED_100000, - }, - [LINK_MODE_100GE_BASE_R2] = { - .link_mode_bit_arr = spnic_mag_link_mode_100ge_base_r2, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_100ge_base_r2), - .speed = SPEED_100000, - }, - [LINK_MODE_100GE_BASE_R4] = { - .link_mode_bit_arr = spnic_mag_link_mode_100ge_base_r4, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_100ge_base_r4), - .speed = SPEED_100000, - }, - [LINK_MODE_200GE_BASE_R2] = { - .link_mode_bit_arr = spnic_mag_link_mode_200ge_base_r2, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_200ge_base_r2), - .speed = SPEED_200000, - }, - [LINK_MODE_200GE_BASE_R4] = { - .link_mode_bit_arr = spnic_mag_link_mode_200ge_base_r4, - .arr_size = ARRAY_LEN(spnic_mag_link_mode_200ge_base_r4), - .speed = SPEED_200000, - }, -}; - -#define GET_SUPPORTED_MODE 0 -#define GET_ADVERTISED_MODE 1 - -struct cmd_link_settings { - __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); - __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); - - u32 speed; - u8 duplex; - u8 port; - u8 autoneg; -}; - -#define ETHTOOL_ADD_SUPPORTED_LINK_MODE(ecmd, mode) \ - set_bit(ETHTOOL_LINK_MODE_##mode##_BIT, (ecmd)->supported) -#define ETHTOOL_ADD_ADVERTISED_LINK_MODE(ecmd, mode) \ - set_bit(ETHTOOL_LINK_MODE_##mode##_BIT, (ecmd)->advertising) - -#define ETHTOOL_ADD_SUPPORTED_SPEED_LINK_MODE(ecmd, mode) \ -do { \ - u32 i; \ - for (i = 0; i < hw2ethtool_link_mode_table[mode].arr_size; i++) \ - set_bit(hw2ethtool_link_mode_table[mode].link_mode_bit_arr[i], \ - (ecmd)->supported); \ -} while (0) - -#define ETHTOOL_ADD_ADVERTISED_SPEED_LINK_MODE(ecmd, mode) \ -do { \ - u32 i; \ - for (i = 0; i < hw2ethtool_link_mode_table[mode].arr_size; i++) \ - set_bit(hw2ethtool_link_mode_table[mode].link_mode_bit_arr[i], \ - (ecmd)->advertising); \ -} while (0) - -/* Related to enum mag_cmd_port_speed */ -static u32 hw_to_ethtool_speed[] = { - (u32)SPEED_UNKNOWN, SPEED_10, SPEED_100, SPEED_1000, SPEED_10000, - SPEED_25000, SPEED_40000, SPEED_50000, SPEED_100000, SPEED_200000 -}; - -static int spnic_ethtool_to_hw_speed_level(u32 speed) -{ - int i; - - for (i = 0; i < ARRAY_LEN(hw_to_ethtool_speed); i++) { - if (hw_to_ethtool_speed[i] == speed) - break; - } - - return i; -} - -static void -spnic_add_ethtool_link_mode(struct cmd_link_settings *link_settings, u32 hw_link_mode, u32 name) -{ - u32 link_mode; - - for (link_mode = 0; link_mode < LINK_MODE_MAX_NUMBERS; link_mode++) { - if (hw_link_mode & BIT(link_mode)) { - if (name == GET_SUPPORTED_MODE) - ETHTOOL_ADD_SUPPORTED_SPEED_LINK_MODE(link_settings, link_mode); - else - ETHTOOL_ADD_ADVERTISED_SPEED_LINK_MODE(link_settings, link_mode); - } - } -} - -static int spnic_link_speed_set(struct spnic_nic_dev *nic_dev, - struct cmd_link_settings *link_settings, - struct nic_port_info *port_info) -{ - u8 link_state = 0; - int err; - - if (port_info->supported_mode != LINK_MODE_UNKNOWN) - spnic_add_ethtool_link_mode(link_settings, port_info->supported_mode, - GET_SUPPORTED_MODE); - if (port_info->advertised_mode != LINK_MODE_UNKNOWN) - spnic_add_ethtool_link_mode(link_settings, port_info->advertised_mode, - GET_ADVERTISED_MODE); - - err = spnic_get_link_state(nic_dev->hwdev, &link_state); - if (!err && link_state) { - link_settings->speed = - port_info->speed < ARRAY_LEN(hw_to_ethtool_speed) ? - hw_to_ethtool_speed[port_info->speed] : - (u32)SPEED_UNKNOWN; - - link_settings->duplex = port_info->duplex; - } else { - link_settings->speed = (u32)SPEED_UNKNOWN; - link_settings->duplex = DUPLEX_UNKNOWN; - } - - return 0; -} - -static void spnic_link_port_type(struct cmd_link_settings *link_settings, u8 port_type) -{ - switch (port_type) { - case MAG_CMD_WIRE_TYPE_ELECTRIC: - ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, TP); - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, TP); - link_settings->port = PORT_TP; - break; - - case MAG_CMD_WIRE_TYPE_AOC: - case MAG_CMD_WIRE_TYPE_MM: - case MAG_CMD_WIRE_TYPE_SM: - ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, FIBRE); - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, FIBRE); - link_settings->port = PORT_FIBRE; - break; - - case MAG_CMD_WIRE_TYPE_COPPER: - ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, FIBRE); - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, FIBRE); - link_settings->port = PORT_DA; - break; - - case MAG_CMD_WIRE_TYPE_BACKPLANE: - ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, Backplane); - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Backplane); - link_settings->port = PORT_NONE; - break; - - default: - link_settings->port = PORT_OTHER; - break; - } -} - -static int get_link_pause_settings(struct spnic_nic_dev *nic_dev, - struct cmd_link_settings *link_settings) -{ - struct nic_pause_config nic_pause = {0}; - int err; - - err = spnic_get_pause_info(nic_dev->hwdev, &nic_pause); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to get pauseparam from hw\n"); - return err; - } - - ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, Pause); - if (nic_pause.rx_pause && nic_pause.tx_pause) { - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Pause); - } else if (nic_pause.tx_pause) { - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Asym_Pause); - } else if (nic_pause.rx_pause) { - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Pause); - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Asym_Pause); - } - - return 0; -} - -int get_link_settings(struct net_device *netdev, struct cmd_link_settings *link_settings) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct nic_port_info port_info = {0}; - int err; - - err = spnic_get_port_info(nic_dev->hwdev, &port_info, SPHW_CHANNEL_NIC); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to get port info\n"); - return err; - } - - err = spnic_link_speed_set(nic_dev, link_settings, &port_info); - if (err) - return err; - - spnic_link_port_type(link_settings, port_info.port_type); - - link_settings->autoneg = port_info.autoneg_state == PORT_CFG_AN_ON ? - AUTONEG_ENABLE : AUTONEG_DISABLE; - if (port_info.autoneg_cap) - ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, Autoneg); - if (port_info.autoneg_state == PORT_CFG_AN_ON) - ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Autoneg); - - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) - err = get_link_pause_settings(nic_dev, link_settings); - - return err; -} - -int spnic_get_link_ksettings(struct net_device *netdev, - struct ethtool_link_ksettings *link_settings) -{ - struct cmd_link_settings settings = { { 0 } }; - struct ethtool_link_settings *base = &link_settings->base; - int err; - - ethtool_link_ksettings_zero_link_mode(link_settings, supported); - ethtool_link_ksettings_zero_link_mode(link_settings, advertising); - - err = get_link_settings(netdev, &settings); - if (err) - return err; - - bitmap_copy(link_settings->link_modes.supported, settings.supported, - __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_copy(link_settings->link_modes.advertising, settings.advertising, - __ETHTOOL_LINK_MODE_MASK_NBITS); - - base->autoneg = settings.autoneg; - base->speed = settings.speed; - base->duplex = settings.duplex; - base->port = settings.port; - - return 0; -} - -static bool spnic_is_support_speed(u32 supported_link, u32 speed) -{ - u32 link_mode; - - for (link_mode = 0; link_mode < LINK_MODE_MAX_NUMBERS; link_mode++) { - if (!(supported_link & BIT(link_mode))) - continue; - - if (hw2ethtool_link_mode_table[link_mode].speed == speed) - return true; - } - - return false; -} - -static int spnic_is_speed_legal(struct spnic_nic_dev *nic_dev, - struct nic_port_info *port_info, u32 speed) -{ - struct net_device *netdev = nic_dev->netdev; - int speed_level = 0; - - if (port_info->supported_mode == LINK_MODE_UNKNOWN || - port_info->advertised_mode == LINK_MODE_UNKNOWN) { - nicif_err(nic_dev, drv, netdev, "Unknown supported link modes\n"); - return -EAGAIN; - } - - speed_level = spnic_ethtool_to_hw_speed_level(speed); - if (speed_level >= PORT_SPEED_UNKNOWN || - !spnic_is_support_speed(port_info->supported_mode, speed)) { - nicif_err(nic_dev, drv, netdev, - "Not supported speed: %u\n", speed); - return -EINVAL; - } - - return 0; -} - -static int get_link_settings_type(struct spnic_nic_dev *nic_dev, - u8 autoneg, u32 speed, u32 *set_settings) -{ - struct nic_port_info port_info = {0}; - int err; - - err = spnic_get_port_info(nic_dev->hwdev, &port_info, SPHW_CHANNEL_NIC); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to get current settings\n"); - return -EAGAIN; - } - - /* Alwayse set autonegation */ - if (port_info.autoneg_cap) - *set_settings |= HILINK_LINK_SET_AUTONEG; - - if (autoneg == AUTONEG_ENABLE) { - if (!port_info.autoneg_cap) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Not support autoneg\n"); - return -EOPNOTSUPP; - } - } else if (speed != (u32)SPEED_UNKNOWN) { - /* Set speed only when autoneg is disable */ - err = spnic_is_speed_legal(nic_dev, &port_info, speed); - if (err) - return err; - - *set_settings |= HILINK_LINK_SET_SPEED; - } else { - nicif_err(nic_dev, drv, nic_dev->netdev, "Need to set speed when autoneg is off\n"); - return -EOPNOTSUPP; - } - - return 0; -} - -static int spnic_set_settings_to_hw(struct spnic_nic_dev *nic_dev, - u32 set_settings, u8 autoneg, u32 speed) -{ - struct net_device *netdev = nic_dev->netdev; - struct spnic_link_ksettings settings = {0}; - int speed_level = 0; - char set_link_str[128] = {0}; - int err = 0; - - snprintf(set_link_str, sizeof(set_link_str), "%s", - (set_settings & HILINK_LINK_SET_AUTONEG) ? - (autoneg ? "autong enable " : "autong disable ") : ""); - if (set_settings & HILINK_LINK_SET_SPEED) { - speed_level = spnic_ethtool_to_hw_speed_level(speed); - snprintf(set_link_str, sizeof(set_link_str), - "%sspeed %u ", set_link_str, speed); - } - - settings.valid_bitmap = set_settings; - settings.autoneg = autoneg ? PORT_CFG_AN_ON : PORT_CFG_AN_OFF; - settings.speed = (u8)speed_level; - - err = spnic_set_link_settings(nic_dev->hwdev, &settings); - if (err) - nicif_err(nic_dev, drv, netdev, "Set %sfailed\n", - set_link_str); - else - nicif_info(nic_dev, drv, netdev, "Set %ssuccess\n", - set_link_str); - - return err; -} - -int set_link_settings(struct net_device *netdev, u8 autoneg, u32 speed) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u32 set_settings = 0; - int err = 0; - - err = get_link_settings_type(nic_dev, autoneg, speed, &set_settings); - if (err) - return err; - - if (set_settings) - err = spnic_set_settings_to_hw(nic_dev, set_settings, autoneg, speed); - else - nicif_info(nic_dev, drv, netdev, "Nothing changed, exiting without setting anything\n"); - - return err; -} - -int spnic_set_link_ksettings(struct net_device *netdev, - const struct ethtool_link_ksettings *link_settings) -{ - /* Only support to set autoneg and speed */ - return set_link_settings(netdev, link_settings->base.autoneg, - link_settings->base.speed); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_filter.c b/drivers/net/ethernet/ramaxel/spnic/spnic_filter.c deleted file mode 100644 index d7ca2bed454b..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_filter.c +++ /dev/null @@ -1,411 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/debugfs.h> -#include <linux/module.h> -#include <linux/moduleparam.h> - -#include "sphw_hw.h" -#include "sphw_crm.h" -#include "spnic_nic_dev.h" - -enum spnic_rx_mod { - SPNIC_RX_MODE_UC = 1 << 0, - SPNIC_RX_MODE_MC = 1 << 1, - SPNIC_RX_MODE_BC = 1 << 2, - SPNIC_RX_MODE_MC_ALL = 1 << 3, - SPNIC_RX_MODE_PROMISC = 1 << 4, -}; - -static int spnic_uc_sync(struct net_device *netdev, u8 *addr) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - return spnic_set_mac(nic_dev->hwdev, addr, 0, sphw_global_func_id(nic_dev->hwdev), - SPHW_CHANNEL_NIC); -} - -static int spnic_uc_unsync(struct net_device *netdev, u8 *addr) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - /* The addr is in use */ - if (ether_addr_equal(addr, netdev->dev_addr)) - return 0; - - return spnic_del_mac(nic_dev->hwdev, addr, 0, sphw_global_func_id(nic_dev->hwdev), - SPHW_CHANNEL_NIC); -} - -void spnic_clean_mac_list_filter(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - struct spnic_mac_filter *ftmp = NULL; - struct spnic_mac_filter *f = NULL; - - list_for_each_entry_safe(f, ftmp, &nic_dev->uc_filter_list, list) { - if (f->state == SPNIC_MAC_HW_SYNCED) - spnic_uc_unsync(netdev, f->addr); - list_del(&f->list); - kfree(f); - } - - list_for_each_entry_safe(f, ftmp, &nic_dev->mc_filter_list, list) { - if (f->state == SPNIC_MAC_HW_SYNCED) - spnic_uc_unsync(netdev, f->addr); - list_del(&f->list); - kfree(f); - } -} - -static struct spnic_mac_filter *spnic_find_mac(struct list_head *filter_list, u8 *addr) -{ - struct spnic_mac_filter *f = NULL; - - list_for_each_entry(f, filter_list, list) { - if (ether_addr_equal(addr, f->addr)) - return f; - } - return NULL; -} - -static struct spnic_mac_filter *spnic_add_filter(struct spnic_nic_dev *nic_dev, - struct list_head *mac_filter_list, u8 *addr) -{ - struct spnic_mac_filter *f; - - f = kzalloc(sizeof(*f), GFP_ATOMIC); - if (!f) - goto out; - - ether_addr_copy(f->addr, addr); - - INIT_LIST_HEAD(&f->list); - list_add_tail(&f->list, mac_filter_list); - - f->state = SPNIC_MAC_WAIT_HW_SYNC; - set_bit(SPNIC_MAC_FILTER_CHANGED, &nic_dev->flags); - -out: - return f; -} - -static void spnic_del_filter(struct spnic_nic_dev *nic_dev, struct spnic_mac_filter *f) -{ - set_bit(SPNIC_MAC_FILTER_CHANGED, &nic_dev->flags); - - if (f->state == SPNIC_MAC_WAIT_HW_SYNC) { - /* have not added to hw, delete it directly */ - list_del(&f->list); - kfree(f); - return; - } - - f->state = SPNIC_MAC_WAIT_HW_UNSYNC; -} - -static struct spnic_mac_filter *spnic_mac_filter_entry_clone(struct spnic_mac_filter *src) -{ - struct spnic_mac_filter *f; - - f = kzalloc(sizeof(*f), GFP_ATOMIC); - if (!f) - return NULL; - - *f = *src; - INIT_LIST_HEAD(&f->list); - - return f; -} - -static void spnic_undo_del_filter_entries(struct list_head *filter_list, struct list_head *from) -{ - struct spnic_mac_filter *ftmp = NULL; - struct spnic_mac_filter *f = NULL; - - list_for_each_entry_safe(f, ftmp, from, list) { - if (spnic_find_mac(filter_list, f->addr)) - continue; - - if (f->state == SPNIC_MAC_HW_SYNCED) - f->state = SPNIC_MAC_WAIT_HW_UNSYNC; - - list_move_tail(&f->list, filter_list); - } -} - -static void spnic_undo_add_filter_entries(struct list_head *filter_list, struct list_head *from) -{ - struct spnic_mac_filter *ftmp = NULL; - struct spnic_mac_filter *tmp = NULL; - struct spnic_mac_filter *f = NULL; - - list_for_each_entry_safe(f, ftmp, from, list) { - tmp = spnic_find_mac(filter_list, f->addr); - if (tmp && tmp->state == SPNIC_MAC_HW_SYNCED) - tmp->state = SPNIC_MAC_WAIT_HW_SYNC; - } -} - -static void spnic_cleanup_filter_list(struct list_head *head) -{ - struct spnic_mac_filter *ftmp = NULL; - struct spnic_mac_filter *f = NULL; - - list_for_each_entry_safe(f, ftmp, head, list) { - list_del(&f->list); - kfree(f); - } -} - -static int spnic_mac_filter_sync_hw(struct spnic_nic_dev *nic_dev, struct list_head *del_list, - struct list_head *add_list) -{ - struct net_device *netdev = nic_dev->netdev; - struct spnic_mac_filter *ftmp = NULL; - struct spnic_mac_filter *f = NULL; - int err = 0, add_count = 0; - - if (!list_empty(del_list)) { - list_for_each_entry_safe(f, ftmp, del_list, list) { - err = spnic_uc_unsync(netdev, f->addr); - if (err) { /* ignore errors when delete mac */ - nic_err(&nic_dev->pdev->dev, "Failed to delete mac\n"); - } - - list_del(&f->list); - kfree(f); - } - } - - if (!list_empty(add_list)) { - list_for_each_entry_safe(f, ftmp, add_list, list) { - err = spnic_uc_sync(netdev, f->addr); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to add mac\n"); - return err; - } - - add_count++; - list_del(&f->list); - kfree(f); - } - } - - return add_count; -} - -static int spnic_mac_filter_sync(struct spnic_nic_dev *nic_dev, - struct list_head *mac_filter_list, bool uc) -{ - struct net_device *netdev = nic_dev->netdev; - struct list_head tmp_del_list, tmp_add_list; - struct spnic_mac_filter *fclone = NULL; - struct spnic_mac_filter *ftmp = NULL; - struct spnic_mac_filter *f = NULL; - int err = 0, add_count = 0; - - INIT_LIST_HEAD(&tmp_del_list); - INIT_LIST_HEAD(&tmp_add_list); - - list_for_each_entry_safe(f, ftmp, mac_filter_list, list) { - if (f->state != SPNIC_MAC_WAIT_HW_UNSYNC) - continue; - - f->state = SPNIC_MAC_HW_UNSYNCED; - list_move_tail(&f->list, &tmp_del_list); - } - - list_for_each_entry_safe(f, ftmp, mac_filter_list, list) { - if (f->state != SPNIC_MAC_WAIT_HW_SYNC) - continue; - - fclone = spnic_mac_filter_entry_clone(f); - if (!fclone) { - err = -ENOMEM; - break; - } - - f->state = SPNIC_MAC_HW_SYNCED; - list_add_tail(&fclone->list, &tmp_add_list); - } - - if (err) { - spnic_undo_del_filter_entries(mac_filter_list, &tmp_del_list); - spnic_undo_add_filter_entries(mac_filter_list, &tmp_add_list); - nicif_err(nic_dev, drv, netdev, "Failed to clone mac_filter_entry\n"); - - spnic_cleanup_filter_list(&tmp_del_list); - spnic_cleanup_filter_list(&tmp_add_list); - return -ENOMEM; - } - - add_count = spnic_mac_filter_sync_hw(nic_dev, &tmp_del_list, &tmp_add_list); - if (list_empty(&tmp_add_list)) - return add_count; - - /* there are errors when add mac to hw, delete all mac in hw */ - spnic_undo_add_filter_entries(mac_filter_list, &tmp_add_list); - /* VF don't support to enter promisc mode, - * so we can't delete any other uc mac - */ - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev) || !uc) { - list_for_each_entry_safe(f, ftmp, mac_filter_list, list) { - if (f->state != SPNIC_MAC_HW_SYNCED) - continue; - - fclone = spnic_mac_filter_entry_clone(f); - if (!fclone) - break; - - f->state = SPNIC_MAC_WAIT_HW_SYNC; - list_add_tail(&fclone->list, &tmp_del_list); - } - } - - spnic_cleanup_filter_list(&tmp_add_list); - spnic_mac_filter_sync_hw(nic_dev, &tmp_del_list, &tmp_add_list); - - /* need to enter promisc/allmulti mode */ - return -ENOMEM; -} - -static void spnic_mac_filter_sync_all(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - int add_count; - - if (test_bit(SPNIC_MAC_FILTER_CHANGED, &nic_dev->flags)) { - clear_bit(SPNIC_MAC_FILTER_CHANGED, &nic_dev->flags); - add_count = spnic_mac_filter_sync(nic_dev, &nic_dev->uc_filter_list, true); - if (add_count < 0 && SPNIC_SUPPORT_PROMISC(nic_dev->hwdev)) { - set_bit(SPNIC_PROMISC_FORCE_ON, &nic_dev->rx_mod_state); - nicif_info(nic_dev, drv, netdev, "Promisc mode forced on\n"); - } else if (add_count) { - clear_bit(SPNIC_PROMISC_FORCE_ON, &nic_dev->rx_mod_state); - } - - add_count = spnic_mac_filter_sync(nic_dev, &nic_dev->mc_filter_list, false); - if (add_count < 0 && SPNIC_SUPPORT_ALLMULTI(nic_dev->hwdev)) { - set_bit(SPNIC_ALLMULTI_FORCE_ON, &nic_dev->rx_mod_state); - nicif_info(nic_dev, drv, netdev, "All multicast mode forced on\n"); - } else if (add_count) { - clear_bit(SPNIC_ALLMULTI_FORCE_ON, &nic_dev->rx_mod_state); - } - } -} - -#define SPNIC_DEFAULT_RX_MODE (SPNIC_RX_MODE_UC | SPNIC_RX_MODE_MC | \ - SPNIC_RX_MODE_BC) - -static void spnic_update_mac_filter(struct spnic_nic_dev *nic_dev, - struct netdev_hw_addr_list *src_list, - struct list_head *filter_list) -{ - struct spnic_mac_filter *filter = NULL; - struct spnic_mac_filter *ftmp = NULL; - struct spnic_mac_filter *f = NULL; - struct netdev_hw_addr *ha = NULL; - - /* add addr if not already in the filter list */ - netif_addr_lock_bh(nic_dev->netdev); - netdev_hw_addr_list_for_each(ha, src_list) { - filter = spnic_find_mac(filter_list, ha->addr); - if (!filter) - spnic_add_filter(nic_dev, filter_list, ha->addr); - else if (filter->state == SPNIC_MAC_WAIT_HW_UNSYNC) - filter->state = SPNIC_MAC_HW_SYNCED; - } - netif_addr_unlock_bh(nic_dev->netdev); - - /* delete addr if not in netdev list */ - list_for_each_entry_safe(f, ftmp, filter_list, list) { - bool found = false; - - netif_addr_lock_bh(nic_dev->netdev); - netdev_hw_addr_list_for_each(ha, src_list) - if (ether_addr_equal(ha->addr, f->addr)) { - found = true; - break; - } - netif_addr_unlock_bh(nic_dev->netdev); - - if (found) - continue; - - spnic_del_filter(nic_dev, f); - } -} - -static void update_mac_filter(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - - if (test_and_clear_bit(SPNIC_UPDATE_MAC_FILTER, &nic_dev->flags)) { - spnic_update_mac_filter(nic_dev, &netdev->uc, &nic_dev->uc_filter_list); - spnic_update_mac_filter(nic_dev, &netdev->mc, &nic_dev->mc_filter_list); - } -} - -static void sync_rx_mode_to_hw(struct spnic_nic_dev *nic_dev, int promisc_en, - int allmulti_en) -{ - struct net_device *netdev = nic_dev->netdev; - u32 rx_mod = SPNIC_DEFAULT_RX_MODE; - int err; - - rx_mod |= (promisc_en ? SPNIC_RX_MODE_PROMISC : 0); - rx_mod |= (allmulti_en ? SPNIC_RX_MODE_MC_ALL : 0); - - if (promisc_en != test_bit(SPNIC_HW_PROMISC_ON, &nic_dev->rx_mod_state)) - nicif_info(nic_dev, drv, netdev, "%s promisc mode\n", - promisc_en ? "Enter" : "Left"); - if (allmulti_en != - test_bit(SPNIC_HW_ALLMULTI_ON, &nic_dev->rx_mod_state)) - nicif_info(nic_dev, drv, netdev, "%s all_multi mode\n", - allmulti_en ? "Enter" : "Left"); - - err = spnic_set_rx_mode(nic_dev->hwdev, rx_mod); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to set rx_mode\n"); - return; - } - - promisc_en ? set_bit(SPNIC_HW_PROMISC_ON, &nic_dev->rx_mod_state) : - clear_bit(SPNIC_HW_PROMISC_ON, &nic_dev->rx_mod_state); - - allmulti_en ? set_bit(SPNIC_HW_ALLMULTI_ON, &nic_dev->rx_mod_state) : - clear_bit(SPNIC_HW_ALLMULTI_ON, &nic_dev->rx_mod_state); -} - -void spnic_set_rx_mode_work(struct work_struct *work) -{ - struct spnic_nic_dev *nic_dev = - container_of(work, struct spnic_nic_dev, rx_mode_work); - struct net_device *netdev = nic_dev->netdev; - int promisc_en = 0, allmulti_en = 0; - - update_mac_filter(nic_dev); - - spnic_mac_filter_sync_all(nic_dev); - - if (SPNIC_SUPPORT_PROMISC(nic_dev->hwdev)) - promisc_en = !!(netdev->flags & IFF_PROMISC) || - test_bit(SPNIC_PROMISC_FORCE_ON, &nic_dev->rx_mod_state); - - if (SPNIC_SUPPORT_ALLMULTI(nic_dev->hwdev)) - allmulti_en = !!(netdev->flags & IFF_ALLMULTI) || - test_bit(SPNIC_ALLMULTI_FORCE_ON, &nic_dev->rx_mod_state); - - if (promisc_en != test_bit(SPNIC_HW_PROMISC_ON, &nic_dev->rx_mod_state) || - allmulti_en != test_bit(SPNIC_HW_ALLMULTI_ON, &nic_dev->rx_mod_state)) - sync_rx_mode_to_hw(nic_dev, promisc_en, allmulti_en); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_irq.c b/drivers/net/ethernet/ramaxel/spnic/spnic_irq.c deleted file mode 100644 index 872a94a73590..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_irq.c +++ /dev/null @@ -1,178 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/debugfs.h> - -#include "sphw_hw.h" -#include "sphw_crm.h" -#include "spnic_nic_io.h" -#include "spnic_nic_dev.h" -#include "spnic_tx.h" -#include "spnic_rx.h" - -int spnic_poll(struct napi_struct *napi, int budget) -{ - struct spnic_irq *irq_cfg = container_of(napi, struct spnic_irq, napi); - struct spnic_nic_dev *nic_dev = netdev_priv(irq_cfg->netdev); - int tx_pkts, rx_pkts; - - rx_pkts = spnic_rx_poll(irq_cfg->rxq, budget); - - tx_pkts = spnic_tx_poll(irq_cfg->txq, budget); - - if (tx_pkts >= budget || rx_pkts >= budget) - return budget; - - napi_complete(napi); - - sphw_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, SPHW_MSIX_ENABLE); - - return max(tx_pkts, rx_pkts); -} - -static void qp_add_napi(struct spnic_irq *irq_cfg) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(irq_cfg->netdev); - - netif_napi_add(nic_dev->netdev, &irq_cfg->napi, spnic_poll, nic_dev->poll_weight); - napi_enable(&irq_cfg->napi); -} - -static void qp_del_napi(struct spnic_irq *irq_cfg) -{ - napi_disable(&irq_cfg->napi); - netif_napi_del(&irq_cfg->napi); -} - -static irqreturn_t qp_irq(int irq, void *data) -{ - struct spnic_irq *irq_cfg = (struct spnic_irq *)data; - struct spnic_nic_dev *nic_dev = netdev_priv(irq_cfg->netdev); - - /* 1 is resend_timer */ - sphw_misx_intr_clear_resend_bit(nic_dev->hwdev, irq_cfg->msix_entry_idx, 1); - - napi_schedule(&irq_cfg->napi); - return IRQ_HANDLED; -} - -static int spnic_request_irq(struct spnic_irq *irq_cfg, u16 q_id) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(irq_cfg->netdev); - struct interrupt_info info = {0}; - int err; - - qp_add_napi(irq_cfg); - - info.msix_index = irq_cfg->msix_entry_idx; - info.lli_set = 0; - info.interrupt_coalesc_set = 1; - info.pending_limt = nic_dev->intr_coalesce[q_id].pending_limt; - info.coalesc_timer_cfg = nic_dev->intr_coalesce[q_id].coalesce_timer_cfg; - info.resend_timer_cfg = nic_dev->intr_coalesce[q_id].resend_timer_cfg; - nic_dev->rxqs[q_id].last_coalesc_timer_cfg = - nic_dev->intr_coalesce[q_id].coalesce_timer_cfg; - nic_dev->rxqs[q_id].last_pending_limt = nic_dev->intr_coalesce[q_id].pending_limt; - err = sphw_set_interrupt_cfg(nic_dev->hwdev, info, SPHW_CHANNEL_NIC); - if (err) { - nicif_err(nic_dev, drv, irq_cfg->netdev, - "Failed to set RX interrupt coalescing attribute.\n"); - qp_del_napi(irq_cfg); - return err; - } - - err = request_irq(irq_cfg->irq_id, &qp_irq, 0, irq_cfg->irq_name, irq_cfg); - if (err) { - nicif_err(nic_dev, drv, irq_cfg->netdev, "Failed to request Rx irq\n"); - qp_del_napi(irq_cfg); - return err; - } - - irq_set_affinity_hint(irq_cfg->irq_id, &irq_cfg->affinity_mask); - - return 0; -} - -static void spnic_release_irq(struct spnic_irq *irq_cfg) -{ - irq_set_affinity_hint(irq_cfg->irq_id, NULL); - synchronize_irq(irq_cfg->irq_id); - free_irq(irq_cfg->irq_id, irq_cfg); - qp_del_napi(irq_cfg); -} - -int spnic_qps_irq_init(struct spnic_nic_dev *nic_dev) -{ - struct pci_dev *pdev = nic_dev->pdev; - struct irq_info *qp_irq_info = NULL; - struct spnic_irq *irq_cfg = NULL; - u16 q_id, i; - u32 local_cpu; - int err; - - for (q_id = 0; q_id < nic_dev->q_params.num_qps; q_id++) { - qp_irq_info = &nic_dev->qps_irq_info[q_id]; - irq_cfg = &nic_dev->q_params.irq_cfg[q_id]; - - irq_cfg->irq_id = qp_irq_info->irq_id; - irq_cfg->msix_entry_idx = qp_irq_info->msix_entry_idx; - irq_cfg->netdev = nic_dev->netdev; - irq_cfg->txq = &nic_dev->txqs[q_id]; - irq_cfg->rxq = &nic_dev->rxqs[q_id]; - nic_dev->rxqs[q_id].irq_cfg = irq_cfg; - - local_cpu = cpumask_local_spread(q_id, dev_to_node(&pdev->dev)); - cpumask_set_cpu(local_cpu, &irq_cfg->affinity_mask); - - snprintf(irq_cfg->irq_name, sizeof(irq_cfg->irq_name), - "%s_qp%u", nic_dev->netdev->name, q_id); - - err = spnic_request_irq(irq_cfg, q_id); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to request Rx irq\n"); - goto req_tx_irq_err; - } - - sphw_set_msix_auto_mask_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, - SPHW_SET_MSIX_AUTO_MASK); - sphw_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, SPHW_MSIX_ENABLE); - } - - INIT_DELAYED_WORK(&nic_dev->moderation_task, spnic_auto_moderation_work); - - return 0; - -req_tx_irq_err: - for (i = 0; i < q_id; i++) { - irq_cfg = &nic_dev->q_params.irq_cfg[i]; - sphw_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, SPHW_MSIX_DISABLE); - sphw_set_msix_auto_mask_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, - SPHW_CLR_MSIX_AUTO_MASK); - spnic_release_irq(irq_cfg); - } - - return err; -} - -void spnic_qps_irq_deinit(struct spnic_nic_dev *nic_dev) -{ - struct spnic_irq *irq_cfg = NULL; - u16 q_id; - - for (q_id = 0; q_id < nic_dev->q_params.num_qps; q_id++) { - irq_cfg = &nic_dev->q_params.irq_cfg[q_id]; - sphw_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, SPHW_MSIX_DISABLE); - sphw_set_msix_auto_mask_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, - SPHW_CLR_MSIX_AUTO_MASK); - spnic_release_irq(irq_cfg); - } -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_lld.c b/drivers/net/ethernet/ramaxel/spnic/spnic_lld.c deleted file mode 100644 index f09a4c186aae..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_lld.c +++ /dev/null @@ -1,937 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [COMM]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/io-mapping.h> -#include <linux/interrupt.h> -#include <linux/inetdevice.h> -#include <net/addrconf.h> -#include <linux/time.h> -#include <linux/timex.h> -#include <linux/rtc.h> -#include <linux/aer.h> -#include <linux/debugfs.h> - -#include "sphw_common.h" -#include "sphw_mt.h" -#include "sphw_crm.h" -#include "spnic_lld.h" -#include "spnic_pci_id_tbl.h" -#include "spnic_sriov.h" -#include "spnic_dev_mgmt.h" -#include "sphw_hw.h" -#include "spnic_nic_dev.h" - -static bool disable_vf_load; -module_param(disable_vf_load, bool, 0444); -MODULE_PARM_DESC(disable_vf_load, "Disable virtual functions probe or not - default is false"); - -static bool disable_attach; -module_param(disable_attach, bool, 0444); -MODULE_PARM_DESC(disable_attach, "disable_attach or not - default is false"); - -#define SPNIC_WAIT_SRIOV_CFG_TIMEOUT 15000 -#define SPNIC_SYNC_YEAR_OFFSET 1900 - -MODULE_AUTHOR("Ramaxel Technologies CO., Ltd"); -MODULE_DESCRIPTION(SPNIC_DRV_DESC); -MODULE_VERSION(SPNIC_DRV_VERSION); -MODULE_LICENSE("GPL"); - -struct spnic_uld_info g_uld_info[SERVICE_T_MAX] = { {0} }; - -#define SPHW_EVENT_PROCESS_TIMEOUT 10000 - -static const char *s_uld_name[SERVICE_T_MAX] = { - "nic", "ovs", "roce", "toe", "ioe", - "fc", "vbs", "ipsec", "virtio", "migrate"}; - -static int attach_uld(struct spnic_pcidev *dev, enum sphw_service_type type, - struct spnic_uld_info *uld_info) -{ - void *uld_dev = NULL; - int err; - - mutex_lock(&dev->pdev_mutex); - - if (dev->uld_dev[type]) { - sdk_err(&dev->pcidev->dev, "%s driver has attached to pcie device\n", - s_uld_name[type]); - err = 0; - goto out_unlock; - } - - err = uld_info->probe(&dev->lld_dev, &uld_dev, dev->uld_dev_name[type]); - if (err || !uld_dev) { - sdk_err(&dev->pcidev->dev, "Failed to add object for %s driver to pcie device\n", - s_uld_name[type]); - goto probe_failed; - } - - dev->uld_dev[type] = uld_dev; - mutex_unlock(&dev->pdev_mutex); - - sdk_info(&dev->pcidev->dev, "Attach %s driver to pcie device succeed\n", s_uld_name[type]); - return 0; - -probe_failed: -out_unlock: - mutex_unlock(&dev->pdev_mutex); - - return err; -} - -static void detach_uld(struct spnic_pcidev *dev, enum sphw_service_type type) -{ - struct spnic_uld_info *uld_info = &g_uld_info[type]; - unsigned long end; - bool timeout = true; - - mutex_lock(&dev->pdev_mutex); - if (!dev->uld_dev[type]) { - mutex_unlock(&dev->pdev_mutex); - return; - } - - end = jiffies + msecs_to_jiffies(SPHW_EVENT_PROCESS_TIMEOUT); - do { - if (!test_and_set_bit(type, &dev->state)) { - timeout = false; - break; - } - usleep_range(900, 1000); - } while (time_before(jiffies, end)); - - if (timeout && !test_and_set_bit(type, &dev->state)) - timeout = false; - - uld_info->remove(&dev->lld_dev, dev->uld_dev[type]); - dev->uld_dev[type] = NULL; - if (!timeout) - clear_bit(type, &dev->state); - - sdk_info(&dev->pcidev->dev, "Detach %s driver from pcie device succeed\n", - s_uld_name[type]); - mutex_unlock(&dev->pdev_mutex); -} - -static void attach_ulds(struct spnic_pcidev *dev) -{ - enum sphw_service_type type; - struct pci_dev *pdev = dev->pcidev; - - for (type = SERVICE_T_NIC; type < SERVICE_T_MAX; type++) { - if (g_uld_info[type].probe) { - if (pdev->is_virtfn && (!spnic_get_vf_service_load(pdev, (u16)type))) { - sdk_info(&pdev->dev, "VF device disable service_type = %d load in host\n", - type); - continue; - } - attach_uld(dev, type, &g_uld_info[type]); - } - } -} - -static void detach_ulds(struct spnic_pcidev *dev) -{ - enum sphw_service_type type; - - for (type = SERVICE_T_MAX - 1; type > SERVICE_T_NIC; type--) { - if (g_uld_info[type].probe) - detach_uld(dev, type); - } - - if (g_uld_info[SERVICE_T_NIC].probe) - detach_uld(dev, SERVICE_T_NIC); -} - -int spnic_register_uld(enum sphw_service_type type, struct spnic_uld_info *uld_info) -{ - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - - if (type >= SERVICE_T_MAX) { - pr_err("Unknown type %d of up layer driver to register\n", type); - return -EINVAL; - } - - if (!uld_info || !uld_info->probe || !uld_info->remove) { - pr_err("Invalid information of %s driver to register\n", s_uld_name[type]); - return -EINVAL; - } - - lld_hold(); - - if (g_uld_info[type].probe) { - pr_err("%s driver has registered\n", s_uld_name[type]); - lld_put(); - return -EINVAL; - } - - memcpy(&g_uld_info[type], uld_info, sizeof(*uld_info)); - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - list_for_each_entry(dev, &chip_node->func_list, node) { - if (attach_uld(dev, type, uld_info)) { - sdk_err(&dev->pcidev->dev, "Attach %s driver to pcie device failed\n", - s_uld_name[type]); - continue; - } - } - } - - lld_put(); - - pr_info("Register %s driver succeed\n", s_uld_name[type]); - return 0; -} - -void spnic_unregister_uld(enum sphw_service_type type) -{ - struct card_node *chip_node = NULL; - struct spnic_pcidev *dev = NULL; - struct spnic_uld_info *uld_info = NULL; - - if (type >= SERVICE_T_MAX) { - pr_err("Unknown type %d of up layer driver to unregister\n", type); - return; - } - - lld_hold(); - list_for_each_entry(chip_node, &g_spnic_chip_list, node) { - /* detach vf first */ - list_for_each_entry(dev, &chip_node->func_list, node) { - if (sphw_func_type(dev->hwdev) != TYPE_VF) - continue; - - detach_uld(dev, type); - } - - list_for_each_entry(dev, &chip_node->func_list, node) { - if (sphw_func_type(dev->hwdev) == TYPE_VF) - continue; - - detach_uld(dev, type); - } - } - - uld_info = &g_uld_info[type]; - memset(uld_info, 0, sizeof(*uld_info)); - lld_put(); -} - -int spnic_attach_nic(struct spnic_lld_dev *lld_dev) -{ - struct spnic_pcidev *dev = NULL; - - if (!lld_dev) - return -EINVAL; - - dev = container_of(lld_dev, struct spnic_pcidev, lld_dev); - return attach_uld(dev, SERVICE_T_NIC, &g_uld_info[SERVICE_T_NIC]); -} - -void spnic_detach_nic(struct spnic_lld_dev *lld_dev) -{ - struct spnic_pcidev *dev = NULL; - - if (!lld_dev) - return; - - dev = container_of(lld_dev, struct spnic_pcidev, lld_dev); - detach_uld(dev, SERVICE_T_NIC); -} - -static void sphw_sync_time_to_fmw(struct spnic_pcidev *pdev_pri) -{ - struct tm tm = {0}; - u64 tv_msec; - int err; - - tv_msec = ktime_to_ms(ktime_get_real()); - err = sphw_sync_time(pdev_pri->hwdev, tv_msec); - if (err) { - sdk_err(&pdev_pri->pcidev->dev, "Synchronize UTC time to firmware failed, errno:%d.\n", - err); - } else { - time64_to_tm(tv_msec / MSEC_PER_SEC, 0, &tm); - sdk_info(&pdev_pri->pcidev->dev, "Synchronize UTC time to firmware succeed. UTC time %ld-%02d-%02d %02d:%02d:%02d.\n", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, - tm.tm_min, tm.tm_sec); - } -} - -static void send_uld_dev_event(struct spnic_pcidev *dev, - struct sphw_event_info *event) -{ - enum sphw_service_type type; - - for (type = SERVICE_T_NIC; type < SERVICE_T_MAX; type++) { - if (test_and_set_bit(type, &dev->state)) { - sdk_warn(&dev->pcidev->dev, "Event: 0x%x can't handler, %s is in detach\n", - event->type, s_uld_name[type]); - continue; - } - - if (g_uld_info[type].event) - g_uld_info[type].event(&dev->lld_dev, dev->uld_dev[type], event); - clear_bit(type, &dev->state); - } -} - -static void send_event_to_dst_pf(struct spnic_pcidev *dev, u16 func_id, - struct sphw_event_info *event) -{ - struct spnic_pcidev *des_dev = NULL; - - lld_hold(); - list_for_each_entry(des_dev, &dev->chip_node->func_list, node) { - if (sphw_func_type(des_dev->hwdev) == TYPE_VF) - continue; - - if (sphw_global_func_id(des_dev->hwdev) == func_id) { - send_uld_dev_event(des_dev, event); - break; - } - } - lld_put(); -} - -void spnic_event_process(void *adapter, struct sphw_event_info *event) -{ - struct spnic_pcidev *dev = adapter; - u16 func_id; - - if (event->type == SPHW_EVENT_FAULT && - event->info.fault_level == FAULT_LEVEL_SERIOUS_FLR && - event->info.event.chip.func_id < sphw_max_pf_num(dev->hwdev)) { - func_id = event->info.event.chip.func_id; - return send_event_to_dst_pf(adapter, func_id, event); - } - - send_uld_dev_event(adapter, event); -} - -#define SPNIC_IS_VF_DEV(pdev) ((pdev)->device == SPNIC_DEV_ID_VF) - -static int mapping_bar(struct pci_dev *pdev, struct spnic_pcidev *pci_adapter) -{ - int cfg_bar; - - cfg_bar = SPNIC_IS_VF_DEV(pdev) ? SPNIC_VF_PCI_CFG_REG_BAR : SPNIC_PF_PCI_CFG_REG_BAR; - - pci_adapter->cfg_reg_base = pci_ioremap_bar(pdev, cfg_bar); - if (!pci_adapter->cfg_reg_base) { - sdk_err(&pdev->dev, "Failed to map configuration regs\n"); - return -ENOMEM; - } - - pci_adapter->intr_reg_base = pci_ioremap_bar(pdev, SPNIC_PCI_INTR_REG_BAR); - if (!pci_adapter->intr_reg_base) { - sdk_err(&pdev->dev, - "Failed to map interrupt regs\n"); - goto map_intr_bar_err; - } - - if (!SPNIC_IS_VF_DEV(pdev)) { - pci_adapter->mgmt_reg_base = pci_ioremap_bar(pdev, SPNIC_PCI_MGMT_REG_BAR); - if (!pci_adapter->mgmt_reg_base) { - sdk_err(&pdev->dev, "Failed to map mgmt regs\n"); - goto map_mgmt_bar_err; - } - } - - pci_adapter->db_base_phy = pci_resource_start(pdev, SPNIC_PCI_DB_BAR); - pci_adapter->db_dwqe_len = pci_resource_len(pdev, SPNIC_PCI_DB_BAR); - pci_adapter->db_base = pci_ioremap_bar(pdev, SPNIC_PCI_DB_BAR); - if (!pci_adapter->db_base) { - sdk_err(&pdev->dev, "Failed to map doorbell regs\n"); - goto map_db_err; - } - - return 0; - -map_db_err: - if (!SPNIC_IS_VF_DEV(pdev)) - iounmap(pci_adapter->mgmt_reg_base); - -map_mgmt_bar_err: - iounmap(pci_adapter->intr_reg_base); - -map_intr_bar_err: - iounmap(pci_adapter->cfg_reg_base); - - return -ENOMEM; -} - -static void unmapping_bar(struct spnic_pcidev *pci_adapter) -{ - iounmap(pci_adapter->db_base); - - if (!SPNIC_IS_VF_DEV(pci_adapter->pcidev)) - iounmap(pci_adapter->mgmt_reg_base); - - iounmap(pci_adapter->intr_reg_base); - iounmap(pci_adapter->cfg_reg_base); -} - -static int spnic_pci_init(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = NULL; - int err; - - pci_adapter = kzalloc(sizeof(*pci_adapter), GFP_KERNEL); - if (!pci_adapter) { - sdk_err(&pdev->dev, "Failed to alloc pci device adapter\n"); - return -ENOMEM; - } - pci_adapter->pcidev = pdev; - mutex_init(&pci_adapter->pdev_mutex); - - pci_set_drvdata(pdev, pci_adapter); - - /* to do CONFIG_PCI_IOV */ - - err = pci_enable_device(pdev); - if (err) { - sdk_err(&pdev->dev, "Failed to enable PCI device\n"); - goto pci_enable_err; - } - - err = pci_request_regions(pdev, SPNIC_NIC_DRV_NAME); - if (err) { - sdk_err(&pdev->dev, "Failed to request regions\n"); - goto pci_regions_err; - } - - pci_enable_pcie_error_reporting(pdev); - - pci_set_master(pdev); - - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); - if (err) { - sdk_warn(&pdev->dev, "Couldn't set 64-bit DMA mask\n"); - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (err) { - sdk_err(&pdev->dev, "Failed to set DMA mask\n"); - goto dma_mask_err; - } - } - - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); - if (err) { - sdk_warn(&pdev->dev, "Couldn't set 64-bit coherent DMA mask\n"); - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); - if (err) { - sdk_err(&pdev->dev, "Failed to set coherent DMA mask\n"); - goto dma_consistnet_mask_err; - } - } - - return 0; - -dma_consistnet_mask_err: -dma_mask_err: - pci_clear_master(pdev); - pci_release_regions(pdev); - -pci_regions_err: - pci_disable_device(pdev); - -pci_enable_err: - pci_set_drvdata(pdev, NULL); - kfree(pci_adapter); - - return err; -} - -static void spnic_pci_deinit(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = pci_get_drvdata(pdev); - - pci_clear_master(pdev); - pci_release_regions(pdev); - pci_disable_pcie_error_reporting(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - kfree(pci_adapter); -} - -#ifdef CONFIG_X86 -/** - * cfg_order_reg - when cpu model is haswell or broadwell, should configure dma - * order register to zero - * @pci_adapter: pci_adapter - **/ -static void cfg_order_reg(struct spnic_pcidev *pci_adapter) -{ - u8 cpu_model[] = {0x3c, 0x3f, 0x45, 0x46, 0x3d, 0x47, 0x4f, 0x56}; - struct cpuinfo_x86 *cpuinfo = NULL; - u32 i; - - if (sphw_func_type(pci_adapter->hwdev) == TYPE_VF) - return; - - cpuinfo = &cpu_data(0); - for (i = 0; i < sizeof(cpu_model); i++) { - if (cpu_model[i] == cpuinfo->x86_model) - sphw_set_pcie_order_cfg(pci_adapter->hwdev); - } -} -#endif - -static int spnic_func_init(struct pci_dev *pdev, struct spnic_pcidev *pci_adapter) -{ - struct sphw_init_para init_para = {0}; - int err; - - init_para.adapter_hdl = pci_adapter; - init_para.pcidev_hdl = pdev; - init_para.dev_hdl = &pdev->dev; - init_para.cfg_reg_base = pci_adapter->cfg_reg_base; - init_para.intr_reg_base = pci_adapter->intr_reg_base; - init_para.mgmt_reg_base = pci_adapter->mgmt_reg_base; - init_para.db_base = pci_adapter->db_base; - init_para.db_base_phy = pci_adapter->db_base_phy; - init_para.db_dwqe_len = pci_adapter->db_dwqe_len; - init_para.hwdev = &pci_adapter->hwdev; - init_para.chip_node = pci_adapter->chip_node; - err = sphw_init_hwdev(&init_para); - if (err) { - pci_adapter->hwdev = NULL; - sdk_err(&pdev->dev, "Failed to initialize hardware device\n"); - return -EFAULT; - } - - pci_adapter->lld_dev.pdev = pdev; - pci_adapter->lld_dev.hwdev = pci_adapter->hwdev; - if (sphw_func_type(pci_adapter->hwdev) != TYPE_VF) - set_bit(SPNIC_FUNC_PERSENT, &pci_adapter->sriov_info.state); - - sphw_event_register(pci_adapter->hwdev, pci_adapter, spnic_event_process); - - if (sphw_func_type(pci_adapter->hwdev) != TYPE_VF) - sphw_sync_time_to_fmw(pci_adapter); - - lld_lock_chip_node(); - list_add_tail(&pci_adapter->node, &pci_adapter->chip_node->func_list); - lld_unlock_chip_node(); - - if (!disable_attach) { - attach_ulds(pci_adapter); -#ifdef CONFIG_X86 - cfg_order_reg(pci_adapter); -#endif - } - - sdk_info(&pdev->dev, "Pcie device probed\n"); - - return 0; -} - -static void spnic_func_deinit(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = pci_get_drvdata(pdev); - - /* When function deinit, disable mgmt initiative report events firstly, - * then flush mgmt work-queue. - */ - sphw_disable_mgmt_msg_report(pci_adapter->hwdev); - - sphw_flush_mgmt_workq(pci_adapter->hwdev); - - lld_lock_chip_node(); - list_del(&pci_adapter->node); - lld_unlock_chip_node(); - - wait_lld_dev_unused(pci_adapter); - - detach_ulds(pci_adapter); - - sphw_event_unregister(pci_adapter->hwdev); - - sphw_free_hwdev(pci_adapter->hwdev); -} - -static inline void wait_sriov_cfg_complete(struct spnic_pcidev *pci_adapter) -{ - struct spnic_sriov_info *sriov_info; - unsigned long end; - - sriov_info = &pci_adapter->sriov_info; - clear_bit(SPNIC_FUNC_PERSENT, &sriov_info->state); - usleep_range(9900, 10000); - - end = jiffies + msecs_to_jiffies(SPNIC_WAIT_SRIOV_CFG_TIMEOUT); - do { - if (!test_bit(SPNIC_SRIOV_ENABLE, &sriov_info->state) && - !test_bit(SPNIC_SRIOV_DISABLE, &sriov_info->state)) - return; - - usleep_range(9900, 10000); - } while (time_before(jiffies, end)); -} - -bool spnic_get_vf_load_state(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = NULL; - struct pci_dev *pf_pdev = NULL; - - if (!pdev) { - pr_err("pdev is null.\n"); - return false; - } - - /* vf used in vm */ - if (pci_is_root_bus(pdev->bus)) - return false; - - if (pdev->is_virtfn) - pf_pdev = pdev->physfn; - else - pf_pdev = pdev; - - pci_adapter = pci_get_drvdata(pf_pdev); - if (!pci_adapter) { - sdk_err(&pdev->dev, "pci_adapter is null.\n"); - return false; - } - - return !pci_adapter->disable_vf_load; -} - -int spnic_set_vf_load_state(struct pci_dev *pdev, bool vf_load_state) -{ - struct spnic_pcidev *pci_adapter = NULL; - - if (!pdev) { - pr_err("pdev is null.\n"); - return -EINVAL; - } - - pci_adapter = pci_get_drvdata(pdev); - if (!pci_adapter) { - sdk_err(&pdev->dev, "pci_adapter is null.\n"); - return -EINVAL; - } - - if (sphw_func_type(pci_adapter->hwdev) == TYPE_VF) - return 0; - - pci_adapter->disable_vf_load = !vf_load_state; - sdk_info(&pci_adapter->pcidev->dev, "Current function %s vf load in host\n", - vf_load_state ? "enable" : "disable"); - - return 0; -} - -bool spnic_get_vf_service_load(struct pci_dev *pdev, u16 service) -{ - struct spnic_pcidev *pci_adapter = NULL; - struct pci_dev *pf_pdev = NULL; - - if (!pdev) { - pr_err("pdev is null.\n"); - return false; - } - - if (pdev->is_virtfn) - pf_pdev = pdev->physfn; - else - pf_pdev = pdev; - - pci_adapter = pci_get_drvdata(pf_pdev); - if (!pci_adapter) { - sdk_err(&pdev->dev, "pci_adapter is null.\n"); - return false; - } - - if (service >= SERVICE_T_MAX) { - sdk_err(&pdev->dev, "service_type = %u state is error\n", - service); - return false; - } - - return !pci_adapter->disable_srv_load[service]; -} - -int spnic_set_vf_service_load(struct pci_dev *pdev, u16 service, bool vf_srv_load) -{ - struct spnic_pcidev *pci_adapter = NULL; - - if (!pdev) { - pr_err("pdev is null.\n"); - return -EINVAL; - } - - if (service >= SERVICE_T_MAX) { - sdk_err(&pdev->dev, "service_type = %u state is error\n", - service); - return -EFAULT; - } - - pci_adapter = pci_get_drvdata(pdev); - if (!pci_adapter) { - sdk_err(&pdev->dev, "pci_adapter is null.\n"); - return -EINVAL; - } - - if (sphw_func_type(pci_adapter->hwdev) == TYPE_VF) - return 0; - - pci_adapter->disable_srv_load[service] = !vf_srv_load; - sdk_info(&pci_adapter->pcidev->dev, "Current function %s vf load in host\n", - vf_srv_load ? "enable" : "disable"); - - return 0; -} - -static int enable_vf_service_state(struct spnic_pcidev *dst_dev, u16 service) -{ - int err; - - err = sphw_get_dev_cap(dst_dev->hwdev); - if (err) { - sdk_err(&dst_dev->pcidev->dev, "Failed to get current device capabilities\n"); - return -EFAULT; - } - return attach_uld(dst_dev, service, &g_uld_info[service]); -} - -int spnic_set_vf_service_state(struct pci_dev *pdev, u16 vf_func_id, u16 service, bool en) -{ - struct spnic_pcidev *dev = NULL; - struct spnic_pcidev *dst_dev = NULL; - int err = -EFAULT; - - if (!pdev) - return -EINVAL; - - dev = pci_get_drvdata(pdev); - if (!dev) - return -EFAULT; - - if (service >= SERVICE_T_MAX) { - sdk_err(&pdev->dev, "Current vf do not supports set service_type = %u state in host\n", - service); - return -EFAULT; - } - - /* find func_idx pci_adapter and disable or enable service */ - lld_hold(); - list_for_each_entry(dst_dev, &dev->chip_node->func_list, node) { - if (sphw_global_func_id(dst_dev->hwdev) != vf_func_id) - continue; - if (en) { - err = enable_vf_service_state(dst_dev, service); - if (err) - sdk_err(&dev->pcidev->dev, "Failed to set functio_id = %u service_type = %u\n", - vf_func_id, service); - } else { - detach_uld(dst_dev, service); - err = 0; - } - break; - } - lld_put(); - - return err; -} - -static void spnic_remove(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = pci_get_drvdata(pdev); - - if (!pci_adapter) - return; - - sdk_info(&pdev->dev, "Pcie device remove begin\n"); - - sphw_detect_hw_present(pci_adapter->hwdev); - - if (sphw_func_type(pci_adapter->hwdev) != TYPE_VF) { - wait_sriov_cfg_complete(pci_adapter); - spnic_pci_sriov_disable(pdev); - } - - spnic_func_deinit(pdev); - - lld_lock_chip_node(); - free_chip_node(pci_adapter); - lld_unlock_chip_node(); - - unmapping_bar(pci_adapter); - spnic_pci_deinit(pdev); - - sdk_info(&pdev->dev, "Pcie device removed\n"); -} - -static int spnic_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - struct spnic_pcidev *pci_adapter = NULL; - int err; - - sdk_info(&pdev->dev, "Pcie device probe begin\n"); - - if (pdev->is_virtfn && (!spnic_get_vf_load_state(pdev))) { - sdk_info(&pdev->dev, "VF device disable load in host\n"); - return 0; - } - - err = spnic_pci_init(pdev); - if (err) - return err; - - pci_adapter = pci_get_drvdata(pdev); - err = mapping_bar(pdev, pci_adapter); - if (err) { - sdk_err(&pdev->dev, "Failed to map bar\n"); - goto map_bar_failed; - } - - pci_adapter->disable_vf_load = disable_vf_load; - pci_adapter->id = *id; - lld_dev_cnt_init(pci_adapter); - - /* if chip information of pcie function exist, add the function into chip */ - lld_lock_chip_node(); - err = alloc_chip_node(pci_adapter); - if (err) { - lld_unlock_chip_node(); - sdk_err(&pdev->dev, - "Failed to add new chip node to global list\n"); - goto alloc_chip_node_fail; - } - - lld_unlock_chip_node(); - - err = spnic_func_init(pdev, pci_adapter); - if (err) - goto func_init_err; - - if (sphw_func_type(pci_adapter->hwdev) != TYPE_VF) { - err = sphw_set_bdf_ctxt(pci_adapter->hwdev, pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); - if (err) { - sdk_err(&pdev->dev, "Failed to set BDF info to MPU\n"); - goto set_bdf_err; - } - } - - return 0; - -set_bdf_err: - spnic_func_deinit(pdev); - -func_init_err: - lld_lock_chip_node(); - free_chip_node(pci_adapter); - lld_unlock_chip_node(); - -alloc_chip_node_fail: - unmapping_bar(pci_adapter); - -map_bar_failed: - spnic_pci_deinit(pdev); - - sdk_err(&pdev->dev, "Pcie device probe failed\n"); - return err; -} - -static const struct pci_device_id spnic_pci_table[] = { - {PCI_VDEVICE(RAMAXEL, SPNIC_DEV_ID_PF_STD), 0}, - {PCI_VDEVICE(RAMAXEL, SPNIC_DEV_ID_VF), 0}, - {PCI_VDEVICE(RAMAXEL, SPNIC_DEV_ID_VF_HV), 0}, - {0, 0} -}; - -MODULE_DEVICE_TABLE(pci, spnic_pci_table); - -/** - * spnic_io_error_detected - called when PCI error is detected - * @pdev: Pointer to PCI device - * @state: The current pci connection state - * - * This function is called after a PCI bus error affecting - * this device has been detected. - * - * Since we only need error detecting not error handling, so we - * always return PCI_ERS_RESULT_CAN_RECOVER to tell the AER - * driver that we don't need reset(error handling). - */ -static pci_ers_result_t spnic_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct spnic_pcidev *pci_adapter = NULL; - - sdk_err(&pdev->dev, - "Uncorrectable error detected, log and cleanup error status: 0x%08x\n", - state); - - pci_aer_clear_nonfatal_status(pdev); - pci_adapter = pci_get_drvdata(pdev); - - if (pci_adapter) - sphw_record_pcie_error(pci_adapter->hwdev); - - return PCI_ERS_RESULT_CAN_RECOVER; -} - -static void spnic_shutdown(struct pci_dev *pdev) -{ - struct spnic_pcidev *pci_adapter = pci_get_drvdata(pdev); - - sdk_err(&pdev->dev, "Shutdown device\n"); - - if (pci_adapter) - sphw_shutdown_hwdev(pci_adapter->hwdev); - - pci_disable_device(pdev); -} - -/* Cause we only need error detecting not error handling, so only error_detected - * callback is enough. - */ -static struct pci_error_handlers spnic_err_handler = { - .error_detected = spnic_io_error_detected, -}; - -static struct pci_driver spnic_driver = { - .name = SPNIC_NIC_DRV_NAME, - .id_table = spnic_pci_table, - .probe = spnic_probe, - .remove = spnic_remove, - .shutdown = spnic_shutdown, - .sriov_configure = spnic_pci_sriov_configure, - .err_handler = &spnic_err_handler -}; - -static __init int spnic_lld_init(void) -{ - int err; - - pr_info("%s - version %s\n", SPNIC_DRV_DESC, SPNIC_DRV_VERSION); - memset(g_uld_info, 0, sizeof(g_uld_info)); - - spnic_lld_lock_init(); - - err = spnic_register_uld(SERVICE_T_NIC, &nic_uld_info); - if (err) { - pr_err("Register spnic uld failed\n"); - return err; - } - - return pci_register_driver(&spnic_driver); -} - -static __exit void spnic_lld_exit(void) -{ - pci_unregister_driver(&spnic_driver); - spnic_unregister_uld(SERVICE_T_NIC); -} - -module_init(spnic_lld_init); -module_exit(spnic_lld_exit); diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_lld.h b/drivers/net/ethernet/ramaxel/spnic/spnic_lld.h deleted file mode 100644 index e1864f1b6c5b..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_lld.h +++ /dev/null @@ -1,75 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_LLD_H -#define SPNIC_LLD_H - -#include "sphw_crm.h" - -struct spnic_lld_dev { - struct pci_dev *pdev; - void *hwdev; -}; - -struct spnic_uld_info { - /* uld_dev: should not return null even the function capability - * is not support the up layer driver - * uld_dev_name: NIC driver should copy net device name. - * FC driver could copy fc device name. - * other up layer driver don`t need copy anything - */ - int (*probe)(struct spnic_lld_dev *lld_dev, void **uld_dev, - char *uld_dev_name); - void (*remove)(struct spnic_lld_dev *lld_dev, void *uld_dev); - int (*suspend)(struct spnic_lld_dev *lld_dev, void *uld_dev, - pm_message_t state); - int (*resume)(struct spnic_lld_dev *lld_dev, void *uld_dev); - void (*event)(struct spnic_lld_dev *lld_dev, void *uld_dev, - struct sphw_event_info *event); - int (*ioctl)(void *uld_dev, u32 cmd, const void *buf_in, u32 in_size, - void *buf_out, u32 *out_size); -}; - -int spnic_register_uld(enum sphw_service_type type, struct spnic_uld_info *uld_info); - -void spnic_unregister_uld(enum sphw_service_type type); - -void *spnic_get_uld_dev_by_pdev(struct pci_dev *pdev, enum sphw_service_type type); - -void *spnic_get_ppf_uld_by_pdev(struct pci_dev *pdev, enum sphw_service_type type); - -int spnic_get_chip_name_by_hwdev(const void *hwdev, char *ifname); - -void *spnic_get_uld_dev_by_ifname(const char *ifname, enum sphw_service_type type); - -int spnic_get_pf_nic_uld_array(struct pci_dev *pdev, u32 *dev_cnt, void *array[]); - -int spnic_get_chip_up_bitmap(struct pci_dev *pdev, bool *is_setted, u8 *valid_up_bitmap); - -int spnic_set_chip_up_bitmap(struct pci_dev *pdev, u8 valid_up_bitmap); - -bool spnic_get_vf_service_load(struct pci_dev *pdev, u16 service); - -int spnic_set_vf_service_load(struct pci_dev *pdev, u16 service, bool vf_srv_load); - -int spnic_set_vf_service_state(struct pci_dev *pdev, u16 vf_func_id, u16 service, bool en); - -bool spnic_get_vf_load_state(struct pci_dev *pdev); - -int spnic_set_vf_load_state(struct pci_dev *pdev, bool vf_load_state); - -int spnic_attach_nic(struct spnic_lld_dev *lld_dev); - -void spnic_detach_nic(struct spnic_lld_dev *lld_dev); - -void lld_hold(void); -void lld_put(void); -void lld_dev_hold(struct spnic_lld_dev *dev); -void lld_dev_put(struct spnic_lld_dev *dev); -struct spnic_lld_dev *spnic_get_lld_dev_by_ifname(const char *ifname); - -void *spnic_get_ppf_hwdev_by_pdev(struct pci_dev *pdev); - -void spnic_send_event_to_uld(struct pci_dev *pdev, enum sphw_service_type type, - struct sphw_event_info *event); -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_mag_cfg.c b/drivers/net/ethernet/ramaxel/spnic/spnic_mag_cfg.c deleted file mode 100644 index d0448d1a6bd3..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_mag_cfg.c +++ /dev/null @@ -1,778 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/etherdevice.h> -#include <linux/if_vlan.h> -#include <linux/ethtool.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/netdevice.h> -#include <linux/module.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "spnic_mag_cmd.h" -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic.h" -#include "sphw_common.h" - -static int mag_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size); -static int mag_msg_to_mgmt_sync_ch(void *hwdev, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, - u16 channel); - -int spnic_set_port_enable(void *hwdev, bool enable, u16 channel) -{ - struct mag_cmd_set_port_enable en_state; - u16 out_size = sizeof(en_state); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - if (sphw_func_type(hwdev) == TYPE_VF) - return 0; - - memset(&en_state, 0, sizeof(en_state)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - en_state.function_id = sphw_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_ch(hwdev, MAG_CMD_SET_PORT_ENABLE, &en_state, - sizeof(en_state), &en_state, &out_size, channel); - if (err || !out_size || en_state.head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set port state, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, en_state.head.status, out_size, channel); - return -EIO; - } - - return 0; -} - -int spnic_get_phy_port_stats(void *hwdev, struct mag_cmd_port_stats *stats) -{ - struct mag_cmd_get_port_stat *port_stats = NULL; - struct mag_cmd_port_stats_info stats_info; - u16 out_size = sizeof(*port_stats); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL); - if (!port_stats) - return -ENOMEM; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&stats_info, 0, sizeof(stats_info)); - stats_info.port_id = sphw_physical_port_id(hwdev); - - err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_PORT_STAT, - &stats_info, sizeof(stats_info), - port_stats, &out_size); - if (err || !out_size || port_stats->head.status) { - nic_err(nic_cfg->dev_hdl, - "Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x\n", - err, port_stats->head.status, out_size); - err = -EIO; - goto out; - } - - memcpy(stats, &port_stats->counter, sizeof(*stats)); - -out: - kfree(port_stats); - - return err; -} - -int spnic_set_port_funcs_state(void *hwdev, bool enable) -{ - return 0; -} - -int spnic_reset_port_link_cfg(void *hwdev) -{ - return 0; -} - -int spnic_force_port_relink(void *hwdev) -{ - return 0; -} - -int spnic_set_autoneg(void *hwdev, bool enable) -{ - /* TODO */ - - return 0; -} - -static int spnic_cfg_loopback_mode(struct spnic_nic_cfg *nic_cfg, u8 opcode, u8 *mode, u8 *enable) -{ - struct mag_cmd_cfg_loopback_mode lp; - u16 out_size = sizeof(lp); - int err; - - memset(&lp, 0, sizeof(lp)); - lp.port_id = sphw_physical_port_id(nic_cfg->hwdev); - lp.opcode = opcode; - if (opcode == MGMT_MSG_CMD_OP_SET) { - lp.lp_mode = *mode; - lp.lp_en = *enable; - } - - err = mag_msg_to_mgmt_sync(nic_cfg->hwdev, MAG_CMD_CFG_LOOPBACK_MODE, - &lp, sizeof(lp), &lp, &out_size); - if (err || !out_size || lp.head.status) { - nic_err(nic_cfg->dev_hdl, - "Failed to %s loopback mode, err: %d, status: 0x%x, out size: 0x%x\n", - opcode == MGMT_MSG_CMD_OP_SET ? "set" : "get", - err, lp.head.status, out_size); - return -EIO; - } - - if (opcode == MGMT_MSG_CMD_OP_GET) { - *mode = lp.lp_mode; - *enable = lp.lp_en; - } - - return 0; -} - -int spnic_get_loopback_mode(void *hwdev, u8 *mode, u8 *enable) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev || !mode || !enable) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - return spnic_cfg_loopback_mode(nic_cfg, MGMT_MSG_CMD_OP_GET, mode, enable); -} - -#define LOOP_MODE_MIN 1 -#define LOOP_MODE_MAX 6 -int spnic_set_loopback_mode(void *hwdev, u8 mode, u8 enable) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if (mode < LOOP_MODE_MIN || mode > LOOP_MODE_MAX) { - nic_err(nic_cfg->dev_hdl, "Invalid loopback mode %u to set\n", - mode); - return -EINVAL; - } - - return spnic_cfg_loopback_mode(nic_cfg, MGMT_MSG_CMD_OP_SET, &mode, &enable); -} - -int spnic_set_led_status(void *hwdev, enum mag_led_type type, enum mag_led_mode mode) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct mag_cmd_set_led_cfg led_info; - u16 out_size = sizeof(led_info); - int err; - - if (!hwdev) - return -EFAULT; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&led_info, 0, sizeof(led_info)); - - led_info.function_id = sphw_global_func_id(hwdev); - led_info.type = type; - led_info.mode = mode; - - err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_SET_LED_CFG, &led_info, - sizeof(led_info), &led_info, &out_size); - if (err || led_info.head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, "Failed to set led status, err: %d, status: 0x%x, out size: 0x%x\n", - err, led_info.head.status, out_size); - return -EIO; - } - - return 0; -} - -int spnic_get_port_info(void *hwdev, struct nic_port_info *port_info, u16 channel) -{ - struct mag_cmd_get_port_info port_msg; - u16 out_size = sizeof(port_msg); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !port_info) - return -EINVAL; - - memset(&port_msg, 0, sizeof(port_msg)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - port_msg.port_id = sphw_physical_port_id(hwdev); - - err = mag_msg_to_mgmt_sync_ch(hwdev, MAG_CMD_GET_PORT_INFO, &port_msg, - sizeof(port_msg), &port_msg, &out_size, - channel); - if (err || !out_size || port_msg.head.status) { - nic_err(nic_cfg->dev_hdl, - "Failed to get port info, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, port_msg.head.status, out_size, channel); - return -EIO; - } - - port_info->autoneg_cap = port_msg.an_support; - port_info->autoneg_state = port_msg.an_en; - port_info->duplex = port_msg.duplex; - port_info->port_type = port_msg.wire_type; - port_info->speed = port_msg.speed; - port_info->fec = port_msg.fec; - port_info->supported_mode = port_msg.supported_mode; - port_info->advertised_mode = port_msg.advertised_mode; - - return 0; -} - -int spnic_get_speed(void *hwdev, enum mag_cmd_port_speed *speed, u16 channel) -{ - struct nic_port_info port_info = {0}; - int err; - - if (!hwdev || !speed) - return -EINVAL; - - err = spnic_get_port_info(hwdev, &port_info, channel); - if (err) - return err; - - *speed = port_info.speed; - - return 0; -} - -int spnic_set_link_settings(void *hwdev, struct spnic_link_ksettings *settings) -{ - struct mag_cmd_set_port_cfg info; - u16 out_size = sizeof(info); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !settings) - return -EINVAL; - - memset(&info, 0, sizeof(info)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - info.port_id = sphw_physical_port_id(hwdev); - info.config_bitmap = settings->valid_bitmap; - info.autoneg = settings->autoneg; - info.speed = settings->speed; - info.fec = settings->fec; - - err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_SET_PORT_CFG, &info, - sizeof(info), &info, &out_size); - if (err || !out_size || info.head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set link settings, err: %d, status: 0x%x, out size: 0x%x\n", - err, info.head.status, out_size); - return -EIO; - } - - return info.head.status; -} - -int spnic_get_link_state(void *hwdev, u8 *link_state) -{ - struct mag_cmd_get_link_status get_link; - u16 out_size = sizeof(get_link); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !link_state) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&get_link, 0, sizeof(get_link)); - get_link.port_id = sphw_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.head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to get link state, err: %d, status: 0x%x, out size: 0x%x\n", - err, get_link.head.status, out_size); - return -EIO; - } - - *link_state = get_link.status; - - return 0; -} - -void spnic_notify_vf_link_status(struct spnic_nic_cfg *nic_cfg, u16 vf_id, u8 link_status) -{ - struct mag_cmd_get_link_status link; - struct vf_data_storage *vf_infos = nic_cfg->vf_infos; - u16 out_size = sizeof(link); - int err; - - memset(&link, 0, sizeof(link)); - if (vf_infos[HW_VF_ID_TO_OS(vf_id)].registered) { - link.status = link_status; - link.port_id = sphw_physical_port_id(nic_cfg->hwdev); - err = sphw_mbox_to_vf(nic_cfg->hwdev, vf_id, SPHW_MOD_HILINK, - MAG_CMD_GET_LINK_STATUS, &link, sizeof(link), &link, - &out_size, 0, SPHW_CHANNEL_NIC); - if (err || !out_size || link.head.status) - nic_err(nic_cfg->dev_hdl, - "Send link change event to VF %d failed, err: %d, status: 0x%x, out_size: 0x%x\n", - HW_VF_ID_TO_OS(vf_id), err, - link.head.status, out_size); - } -} - -void spnic_notify_all_vfs_link_changed(void *hwdev, u8 link_status) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - u16 i; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - nic_cfg->link_status = link_status; - for (i = 1; i <= nic_cfg->max_vfs; i++) { - if (!nic_cfg->vf_infos[HW_VF_ID_TO_OS(i)].link_forced) - spnic_notify_vf_link_status(nic_cfg, i, link_status); - } -} - -static int spnic_get_vf_link_status_msg_handler(struct spnic_nic_cfg *nic_cfg, u16 vf_id, - void *buf_in, u16 in_size, void *buf_out, - u16 *out_size) -{ - struct vf_data_storage *vf_infos = nic_cfg->vf_infos; - struct mag_cmd_get_link_status *get_link = buf_out; - bool link_forced, link_up; - - link_forced = vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced; - link_up = vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up; - - if (link_forced) - get_link->status = link_up ? SPNIC_LINK_UP : SPNIC_LINK_DOWN; - else - get_link->status = nic_cfg->link_status; - - get_link->head.status = 0; - *out_size = sizeof(*get_link); - - return 0; -} - -int spnic_refresh_nic_cfg(void *hwdev, struct nic_port_info *port_info) -{ - /*TO DO */ - return 0; -} - -static void get_port_info(void *hwdev, struct mag_cmd_get_link_status *link_status, - struct sphw_event_link_info *link_info) -{ - struct nic_port_info port_info = {0}; - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (sphw_func_type(hwdev) != TYPE_VF && - link_status->status == SPHW_EVENT_LINK_UP) { - err = spnic_get_port_info(hwdev, &port_info, SPHW_CHANNEL_NIC); - if (err) { - nic_warn(nic_cfg->dev_hdl, "Failed to get port info\n"); - } else { - link_info->valid = 1; - link_info->port_type = port_info.port_type; - link_info->autoneg_cap = port_info.autoneg_cap; - link_info->autoneg_state = port_info.autoneg_state; - link_info->duplex = port_info.duplex; - link_info->speed = port_info.speed; - spnic_refresh_nic_cfg(hwdev, &port_info); - } - } -} - -static void link_status_event_handler(void *hwdev, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size) -{ - struct mag_cmd_get_link_status *link_status = NULL; - struct mag_cmd_get_link_status *ret_link_status = NULL; - struct sphw_event_info event_info = {0}; - struct sphw_event_link_info *link_info = &event_info.link_info; - struct spnic_nic_cfg *nic_cfg = NULL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - link_status = buf_in; - sdk_info(nic_cfg->dev_hdl, "Link status report received, func_id: %u, status: %u\n", - sphw_global_func_id(hwdev), link_status->status); - - sphw_link_event_stats(hwdev, link_status->status); - - /* link event reported only after set vport enable */ - get_port_info(hwdev, link_status, link_info); - - event_info.type = link_status->status ? SPHW_EVENT_LINK_UP : SPHW_EVENT_LINK_DOWN; - - sphw_event_callback(hwdev, &event_info); - - if (sphw_func_type(hwdev) != TYPE_VF) { - spnic_notify_all_vfs_link_changed(hwdev, link_status->status); - ret_link_status = buf_out; - ret_link_status->head.status = 0; - *out_size = sizeof(*ret_link_status); - } -} - -static void cable_plug_event(void *hwdev, void *buf_in, u16 in_size, void *buf_out, u16 *out_size) -{ - struct mag_cmd_wire_event *plug_event = buf_in; - struct spnic_port_routine_cmd *rt_cmd = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - struct sphw_event_info event_info; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - rt_cmd = &nic_cfg->rt_cmd; - - mutex_lock(&nic_cfg->sfp_mutex); - rt_cmd->mpu_send_sfp_abs = false; - rt_cmd->mpu_send_sfp_info = false; - mutex_unlock(&nic_cfg->sfp_mutex); - - memset(&event_info, 0, sizeof(event_info)); - event_info.type = SPHW_EVENT_PORT_MODULE_EVENT; - event_info.module_event.type = plug_event->status ? - SPHW_PORT_MODULE_CABLE_PLUGGED : - SPHW_PORT_MODULE_CABLE_UNPLUGGED; - - *out_size = sizeof(*plug_event); - plug_event = buf_out; - plug_event->head.status = 0; - - sphw_event_callback(hwdev, &event_info); -} - -static void port_sfp_info_event(void *hwdev, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct mag_cmd_get_xsfp_info *sfp_info = buf_in; - struct spnic_port_routine_cmd *rt_cmd = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (in_size != sizeof(*sfp_info)) { - sdk_err(nic_cfg->dev_hdl, "Invalid sfp info cmd, length: %u, should be %ld\n", - in_size, sizeof(*sfp_info)); - return; - } - - rt_cmd = &nic_cfg->rt_cmd; - mutex_lock(&nic_cfg->sfp_mutex); - memcpy(&rt_cmd->std_sfp_info, sfp_info, - sizeof(struct mag_cmd_get_xsfp_info)); - rt_cmd->mpu_send_sfp_info = true; - mutex_unlock(&nic_cfg->sfp_mutex); -} - -static void port_sfp_abs_event(void *hwdev, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct mag_cmd_get_xsfp_present *sfp_abs = buf_in; - struct spnic_port_routine_cmd *rt_cmd = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (in_size != sizeof(*sfp_abs)) { - sdk_err(nic_cfg->dev_hdl, "Invalid sfp absent cmd, length: %u, should be %ld\n", - in_size, sizeof(*sfp_abs)); - return; - } - - rt_cmd = &nic_cfg->rt_cmd; - mutex_lock(&nic_cfg->sfp_mutex); - memcpy(&rt_cmd->abs, sfp_abs, sizeof(struct mag_cmd_get_xsfp_present)); - rt_cmd->mpu_send_sfp_abs = true; - mutex_unlock(&nic_cfg->sfp_mutex); -} - -static bool spnic_if_sfp_absent(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_port_routine_cmd *rt_cmd = NULL; - struct mag_cmd_get_xsfp_present sfp_abs; - u8 port_id = sphw_physical_port_id(hwdev); - u16 out_size = sizeof(sfp_abs); - int err; - bool sfp_abs_status; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&sfp_abs, 0, sizeof(sfp_abs)); - - rt_cmd = &nic_cfg->rt_cmd; - mutex_lock(&nic_cfg->sfp_mutex); - if (rt_cmd->mpu_send_sfp_abs) { - if (rt_cmd->abs.head.status) { - mutex_unlock(&nic_cfg->sfp_mutex); - return true; - } - - sfp_abs_status = (bool)rt_cmd->abs.abs_status; - mutex_unlock(&nic_cfg->sfp_mutex); - return sfp_abs_status; - } - mutex_unlock(&nic_cfg->sfp_mutex); - - sfp_abs.port_id = port_id; - err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_XSFP_PRESENT, - &sfp_abs, sizeof(sfp_abs), &sfp_abs, - &out_size); - if (sfp_abs.head.status || err || !out_size) { - nic_err(nic_cfg->dev_hdl, - "Failed to get port%u sfp absent status, err: %d, status: 0x%x, out size: 0x%x\n", - port_id, err, sfp_abs.head.status, out_size); - return true; - } - - return (sfp_abs.abs_status == 0 ? false : true); -} - -int spnic_get_sfp_eeprom(void *hwdev, u8 *data, u32 len) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_port_routine_cmd *rt_cmd = NULL; - struct mag_cmd_get_xsfp_info sfp_info; - u16 out_size = sizeof(sfp_info); - int err; - - if (!hwdev || !data) - return -EINVAL; - - if (spnic_if_sfp_absent(hwdev)) - return -ENXIO; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&sfp_info, 0, sizeof(sfp_info)); - - rt_cmd = &nic_cfg->rt_cmd; - mutex_lock(&nic_cfg->sfp_mutex); - if (rt_cmd->mpu_send_sfp_info) { - if (rt_cmd->std_sfp_info.head.status) { - mutex_unlock(&nic_cfg->sfp_mutex); - return -EIO; - } - - memcpy(data, rt_cmd->std_sfp_info.sfp_info, len); - mutex_unlock(&nic_cfg->sfp_mutex); - return 0; - } - mutex_unlock(&nic_cfg->sfp_mutex); - - sfp_info.port_id = sphw_physical_port_id(hwdev); - err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_XSFP_INFO, &sfp_info, - sizeof(sfp_info), &sfp_info, &out_size); - if (sfp_info.head.status || err || !out_size) { - nic_err(nic_cfg->dev_hdl, - "Failed to get port%u sfp eeprom information, err: %d, status: 0x%x, out size: 0x%x\n", - sphw_physical_port_id(hwdev), err, - sfp_info.head.status, out_size); - return -EIO; - } - - memcpy(data, sfp_info.sfp_info, len); - - return 0; -} - -int spnic_get_sfp_type(void *hwdev, u8 *sfp_type, u8 *sfp_type_ext) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_port_routine_cmd *rt_cmd = NULL; - u8 sfp_data[STD_SFP_INFO_MAX_SIZE]; - int err; - - if (!hwdev || !sfp_type || !sfp_type_ext) - return -EINVAL; - - if (spnic_if_sfp_absent(hwdev)) - return -ENXIO; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - rt_cmd = &nic_cfg->rt_cmd; - - mutex_lock(&nic_cfg->sfp_mutex); - if (rt_cmd->mpu_send_sfp_info) { - if (rt_cmd->std_sfp_info.head.status) { - mutex_unlock(&nic_cfg->sfp_mutex); - return -EIO; - } - - *sfp_type = rt_cmd->std_sfp_info.sfp_info[0]; - *sfp_type_ext = rt_cmd->std_sfp_info.sfp_info[1]; - mutex_unlock(&nic_cfg->sfp_mutex); - return 0; - } - mutex_unlock(&nic_cfg->sfp_mutex); - - err = spnic_get_sfp_eeprom(hwdev, (u8 *)sfp_data, STD_SFP_INFO_MAX_SIZE); - if (err) - return err; - - *sfp_type = sfp_data[0]; - *sfp_type_ext = sfp_data[1]; - - return 0; -} - -static const struct vf_msg_handler vf_mag_cmd_handler[] = { - { - .cmd = MAG_CMD_GET_LINK_STATUS, - .handler = spnic_get_vf_link_status_msg_handler, - }, -}; - -/* pf/ppf handler mbox msg from vf */ -int spnic_pf_mag_mbox_handler(void *hwdev, void *pri_handle, u16 vf_id, - u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - u32 index, cmd_size = ARRAY_LEN(vf_mag_cmd_handler); - struct spnic_nic_cfg *nic_cfg = NULL; - const struct vf_msg_handler *handler = NULL; - - if (!hwdev) - return -EFAULT; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - for (index = 0; index < cmd_size; index++) { - handler = &vf_mag_cmd_handler[index]; - if (cmd == handler->cmd) - return handler->handler(nic_cfg, vf_id, buf_in, in_size, - buf_out, out_size); - } - - nic_warn(nic_cfg->dev_hdl, "NO handler for mag cmd: %u received from vf id: %u\n", - cmd, vf_id); - - return -EINVAL; -} - -static struct nic_event_handler mag_cmd_handler[] = { - { - .cmd = MAG_CMD_GET_LINK_STATUS, - .handler = link_status_event_handler, - }, - - { - .cmd = MAG_CMD_WIRE_EVENT, - .handler = cable_plug_event, - }, - - { - .cmd = MAG_CMD_GET_XSFP_INFO, - .handler = port_sfp_info_event, - }, - - { - .cmd = MAG_CMD_GET_XSFP_PRESENT, - .handler = port_sfp_abs_event, - }, -}; - -int spnic_mag_event_handler(void *hwdev, void *pri_handle, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - u32 size = ARRAY_LEN(mag_cmd_handler); - u32 i; - - if (!hwdev) - return -EINVAL; - - *out_size = 0; - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - for (i = 0; i < size; i++) { - if (cmd == mag_cmd_handler[i].cmd) { - mag_cmd_handler[i].handler(hwdev, buf_in, in_size, - buf_out, out_size); - break; - } - } - - /* can't find this event cmd */ - if (i == size) - sdk_warn(nic_cfg->dev_hdl, "Unsupported mag event, cmd: %u\n", - cmd); - - return 0; -} - -int spnic_vf_mag_event_handler(void *hwdev, void *pri_handle, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - return spnic_mag_event_handler(hwdev, pri_handle, cmd, buf_in, in_size, buf_out, out_size); -} - -/* pf/ppf handler mgmt cpu report hilink event*/ -void spnic_pf_mag_event_handler(void *hwdev, void *pri_handle, u16 cmd, - void *buf_in, u16 in_size, void *buf_out, u16 *out_size) -{ - spnic_mag_event_handler(hwdev, pri_handle, cmd, buf_in, in_size, buf_out, out_size); -} - -static int _mag_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u16 channel) -{ - u32 i, cmd_cnt = ARRAY_LEN(vf_mag_cmd_handler); - bool cmd_to_pf = false; - - if (sphw_func_type(hwdev) == TYPE_VF) { - for (i = 0; i < cmd_cnt; i++) { - if (cmd == vf_mag_cmd_handler[i].cmd) { - cmd_to_pf = true; - break; - } - } - } - - if (cmd_to_pf) - return sphw_mbox_to_pf(hwdev, SPHW_MOD_HILINK, cmd, buf_in, in_size, buf_out, - out_size, 0, channel); - - return sphw_msg_to_mgmt_sync(hwdev, SPHW_MOD_HILINK, cmd, buf_in, - in_size, buf_out, out_size, 0, channel); -} - -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, SPHW_CHANNEL_NIC); -} - -static int mag_msg_to_mgmt_sync_ch(void *hwdev, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, - u16 channel) -{ - return _mag_msg_to_mgmt_sync(hwdev, cmd, buf_in, in_size, buf_out, - out_size, channel); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_mag_cmd.h b/drivers/net/ethernet/ramaxel/spnic/spnic_mag_cmd.h deleted file mode 100644 index 4e65b7af115b..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_mag_cmd.h +++ /dev/null @@ -1,643 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_MAG_CMD_H -#define SPNIC_MAG_CMD_H - -#include "sphw_mgmt_msg_base.h" - -enum mag_cmd { - SERDES_CMD_PROCESS = 0, - - MAG_CMD_SET_PORT_CFG = 1, - MAG_CMD_SET_PORT_ADAPT = 2, - MAG_CMD_CFG_LOOPBACK_MODE = 3, - - MAG_CMD_GET_PORT_ENABLE = 5, - MAG_CMD_SET_PORT_ENABLE = 6, - MAG_CMD_GET_LINK_STATUS = 7, - MAG_CMD_SET_LINK_FOLLOW = 8, - MAG_CMD_SET_PMA_ENABLE = 9, - MAG_CMD_CFG_FEC_MODE = 10, - - MAG_CMD_CFG_AN_TYPE = 12, /* reserved for furture use */ - - MAG_CMD_SET_PANGEA_ADAPT = 15, - - MAG_CMD_CFG_BIOS_LINK_CFG = 31, - MAG_CMD_RESTORE_LINK_CFG = 32, - MAG_CMD_ACTIVATE_BIOS_LINK_CFG = 33, - - /* LED */ - MAG_CMD_SET_LED_CFG = 50, - - /* PHY */ - MAG_CMD_GET_PHY_INIT_STATUS = 55, /* reserved for furture use */ - - MAG_CMD_GET_XSFP_INFO = 60, - MAG_CMD_SET_XSFP_ENABLE = 61, - MAG_CMD_GET_XSFP_PRESENT = 62, - MAG_CMD_SET_XSFP_RW = 63, - MAG_CMD_CFG_XSFP_TEMPERATURE = 64, - - MAG_CMD_WIRE_EVENT = 100, - MAG_CMD_LINK_ERR_EVENT = 101, - - MAG_CMD_EVENT_PORT_INFO = 150, - MAG_CMD_GET_PORT_STAT = 151, - MAG_CMD_CLR_PORT_STAT = 152, - MAG_CMD_GET_PORT_INFO = 153, - MAG_CMD_GET_PCS_ERR_CNT = 154, - MAG_CMD_GET_MAG_CNT = 155, - MAG_CMD_DUMP_ANTRAIN_INFO = 156, - - MAG_CMD_MAX = 0xFF, -}; - -enum mag_cmd_port_speed { - PORT_SPEED_NOT_SET = 0, - PORT_SPEED_10MB = 1, - PORT_SPEED_100MB = 2, - PORT_SPEED_1GB = 3, - PORT_SPEED_10GB = 4, - PORT_SPEED_25GB = 5, - PORT_SPEED_40GB = 6, - PORT_SPEED_50GB = 7, - PORT_SPEED_100GB = 8, - PORT_SPEED_200GB = 9, - PORT_SPEED_UNKNOWN -}; - -enum mag_cmd_port_an { - PORT_AN_NOT_SET = 0, - PORT_CFG_AN_ON = 1, - PORT_CFG_AN_OFF = 2 -}; - -enum mag_cmd_port_fec { - PORT_FEC_NOT_SET = 0, - PORT_FEC_RSFEC = 1, - PORT_FEC_BASEFEC = 2, - PORT_FEC_NOFEC = 3, - PORT_FEC_LLRSFEC = 4 -}; - -enum mag_cmd_port_lanes { - PORT_LANES_NOT_SET = 0, - PORT_LANES_X1 = 1, - PORT_LANES_X2 = 2, - PORT_LANES_X4 = 4, - PORT_LANES_X8 = 8, /* reserved for future use */ -}; - -enum mag_cmd_port_duplex { - PORT_DUPLEX_HALF = 0, - PORT_DUPLEX_FULL = 1 -}; - -/* mag_cmd_set_port_cfg config bitmap */ -#define MAG_CMD_SET_SPEED 0x1 -#define MAG_CMD_SET_AUTONEG 0x2 -#define MAG_CMD_SET_FEC 0x4 -#define MAG_CMD_SET_LANES 0x8 -struct mag_cmd_set_port_cfg { - struct mgmt_msg_head head; - - u8 port_id; - u8 rsvd0[3]; - - u32 config_bitmap; - u8 speed; - u8 autoneg; - u8 fec; - u8 lanes; - u8 rsvd1[20]; -}; - -/* mag supported/advertised link mode bitmap */ -enum mag_cmd_link_mode { - LINK_MODE_GE = 0, - LINK_MODE_10GE_BASE_R = 1, - LINK_MODE_25GE_BASE_R = 2, - LINK_MODE_40GE_BASE_R4 = 3, - LINK_MODE_50GE_BASE_R = 4, - LINK_MODE_50GE_BASE_R2 = 5, - LINK_MODE_100GE_BASE_R = 6, - LINK_MODE_100GE_BASE_R2 = 7, - LINK_MODE_100GE_BASE_R4 = 8, - LINK_MODE_200GE_BASE_R2 = 9, - LINK_MODE_200GE_BASE_R4 = 10, - LINK_MODE_MAX_NUMBERS, - - LINK_MODE_UNKNOWN = 0xFFFF -}; - -struct mag_cmd_get_port_info { - struct mgmt_msg_head head; - - u8 port_id; - u8 rsvd0[3]; - - u8 wire_type; - u8 an_support; - u8 an_en; - u8 duplex; - - u8 speed; - u8 fec; - u8 lanes; - u8 rsvd1; - - u32 supported_mode; - u32 advertised_mode; - u8 rsvd2[8]; -}; - -#define MAG_CMD_OPCODE_GET 0 -#define MAG_CMD_OPCODE_SET 1 -struct mag_cmd_set_port_adapt { - struct mgmt_msg_head head; - - u8 port_id; - u8 opcode; /* 0:get adapt info 1:set adapt */ - u8 enable; - u8 rsvd0; - u32 speed_mode; - u32 rsvd1[3]; -}; - -#define MAG_CMD_LP_MODE_SDS_S_TX2RX 1 -#define MAG_CMD_LP_MODE_SDS_P_RX2TX 2 -#define MAG_CMD_LP_MODE_SDS_P_TX2RX 3 -#define MAG_CMD_LP_MODE_MAC_RX2TX 4 -#define MAG_CMD_LP_MODE_MAC_TX2RX 5 -#define MAG_CMD_LP_MODE_TXDP2RXDP 6 -struct mag_cmd_cfg_loopback_mode { - struct mgmt_msg_head head; - - u8 port_id; - u8 opcode; /* 0:get loopback mode 1:set loopback mode */ - u8 lp_mode; - u8 lp_en; /* 0:disable 1:enable */ - - u32 rsvd0[2]; -}; - -#define MAG_CMD_PORT_DISABLE 0x0 -#define MAG_CMD_TX_ENABLE 0x1 -#define MAG_CMD_RX_ENABLE 0x2 - -struct mag_cmd_set_port_enable { - struct mgmt_msg_head head; - - u16 function_id; /* function_id should not more than the max support pf_id(32) */ - 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]; -}; - -#define PMA_FOLLOW_DEFAULT 0x0 -#define PMA_FOLLOW_ENABLE 0x1 -#define PMA_FOLLOW_DISABLE 0x2 -/* the physical port disable link follow only when all pf of the port are set to follow disable */ -struct mag_cmd_set_link_follow { - struct mgmt_msg_head head; - - u16 function_id; /* function_id should not more than the max support pf_id(32) */ - u16 rsvd0; - - u8 follow; - u8 rsvd1[3]; -}; - -/* firmware also use this cmd report link event to driver */ -struct mag_cmd_get_link_status { - struct mgmt_msg_head head; - - u8 port_id; - u8 status; /* 0:link down 1:link up */ - u8 rsvd0[2]; -}; - -struct mag_cmd_set_pma_enable { - struct mgmt_msg_head head; - - u16 function_id; /* function_id should not more than the max support pf_id(32) */ - u16 enable; -}; - -struct mag_cmd_cfg_an_type { - struct mgmt_msg_head head; - - u8 port_id; - u8 opcode; /* 0:get an type 1:set an type */ - u8 rsvd0[2]; - - u32 an_type; /* 0:ieee 1:25G/50 eth consortium */ -}; - -struct mag_cmd_cfg_fec_mode { - struct mgmt_msg_head head; - - u8 port_id; - u8 opcode; /* 0:get fec mode 1:set fec mode */ - u8 fec; - u8 rsvd0; -}; - -struct mag_cmd_cfg_bios_link_cfg { - struct mgmt_msg_head head; - - u8 port_id; - u8 opcode; /* 0:get bios link info 1:set bios link cfg */ - u8 clear; - u8 rsvd0; - - u32 wire_type; - u8 an_en; - u8 speed; - u8 fec; - u8 rsvd1; - u32 speed_mode; - u32 rsvd2[3]; -}; - -struct mag_cmd_restore_link_cfg { - struct mgmt_msg_head head; - - u8 port_id; - u8 rsvd[7]; -}; - -struct mag_cmd_activate_bios_link_cfg { - struct mgmt_msg_head head; - - u32 rsvd[8]; -}; - -/* led type */ -enum mag_led_type { - MAG_CMD_LED_TYPE_ALARM = 0x0, - MAG_CMD_LED_TYPE_LOW_SPEED = 0x1, - MAG_CMD_LED_TYPE_HIGH_SPEED = 0x2 -}; - -/* led mode */ -enum mag_led_mode { - MAG_CMD_LED_MODE_DEFAULT = 0x0, - MAG_CMD_LED_MODE_FORCE_ON = 0x1, - MAG_CMD_LED_MODE_FORCE_OFF = 0x2, - MAG_CMD_LED_MODE_FORCE_BLINK_1HZ = 0x3, - MAG_CMD_LED_MODE_FORCE_BLINK_2HZ = 0x4, - MAG_CMD_LED_MODE_FORCE_BLINK_4HZ = 0x5, - MAG_CMD_LED_MODE_1HZ = 0x6, - MAG_CMD_LED_MODE_2HZ = 0x7, - MAG_CMD_LED_MODE_4HZ = 0x8, -}; - -/* the led is report alarm when any pf of the port is alram */ -struct mag_cmd_set_led_cfg { - struct mgmt_msg_head head; - - u16 function_id; - u8 type; - u8 mode; -}; - -#define XSFP_INFO_MAX_SIZE 640 -/* xsfp wire type, refer to cmis protocol definition */ -enum mag_wire_type { - MAG_CMD_WIRE_TYPE_UNKNOWN = 0x0, - MAG_CMD_WIRE_TYPE_MM = 0x1, - MAG_CMD_WIRE_TYPE_SM = 0x2, - MAG_CMD_WIRE_TYPE_COPPER = 0x3, - MAG_CMD_WIRE_TYPE_ACC = 0x4, - MAG_CMD_WIRE_TYPE_BASET = 0x5, - MAG_CMD_WIRE_TYPE_AOC = 0x40, - MAG_CMD_WIRE_TYPE_ELECTRIC = 0x41, - MAG_CMD_WIRE_TYPE_BACKPLANE = 0x42 -}; - -struct mag_cmd_get_xsfp_info { - struct mgmt_msg_head head; - - u8 port_id; - u8 wire_type; - u16 out_len; - u32 rsvd; - u8 sfp_info[XSFP_INFO_MAX_SIZE]; -}; - -#define MAG_CMD_XSFP_DISABLE 0x0 -#define MAG_CMD_XSFP_ENABLE 0x1 - -struct mag_cmd_set_xsfp_enable { - struct mgmt_msg_head head; - - u16 function_id; /* function_id should not more than the max support pf_id(32) */ - u16 rsvd0; - - u8 status; - u8 rsvd1[3]; -}; - -#define MAG_CMD_XSFP_PRESENT 0x0 -#define MAG_CMD_XSFP_ABSENT 0x1 -struct mag_cmd_get_xsfp_present { - struct mgmt_msg_head head; - - u8 port_id; - u8 abs_status; /* 0:present, 1:absent */ - u8 rsvd[2]; -}; - -#define MAG_CMD_XSFP_READ 0x0 -#define MAG_CMD_XSFP_WRITE 0x1 -struct mag_cmd_set_xsfp_rw { - struct mgmt_msg_head head; - - u8 port_id; - u8 operation; /* 0: read; 1: write */ - u8 value; - u8 rsvd0; - u32 devaddr; - u32 offset; - u32 rsvd1; -}; - -struct mag_cmd_cfg_xsfp_temperature { - struct mgmt_msg_head head; - - u8 opcode; /* 0:read 1:write */ - u8 rsvd0[3]; - s32 max_temp; - s32 min_temp; -}; - -struct mag_cmd_get_xsfp_temperature { - struct mgmt_msg_head head; - - s16 sfp_temp[8]; - u8 rsvd[32]; - s32 max_temp; - s32 min_temp; -}; - -/* xsfp plug event */ -struct mag_cmd_wire_event { - struct mgmt_msg_head head; - - u8 port_id; - u8 status; /* 0:present, 1:absent */ - u8 rsvd[2]; -}; - -/* link err type definition */ -#define MAG_CMD_ERR_XSFP_UNKNOWN 0x0 -struct mag_cmd_link_err_event { - struct mgmt_msg_head head; - - u8 port_id; - u8 link_err_type; - u8 rsvd[2]; -}; - -#define MAG_PARAM_TYPE_DEFAULT_CFG 0x0 -#define MAG_PARAM_TYPE_BIOS_CFG 0x1 -#define MAG_PARAM_TYPE_TOOL_CFG 0x2 -#define MAG_PARAM_TYPE_FINAL_CFG 0x3 -#define MAG_PARAM_TYPE_WIRE_INFO 0x4 -#define MAG_PARAM_TYPE_ADAPT_INFO 0x5 -#define MAG_PARAM_TYPE_MAX_CNT 0x6 -struct param_head { - u8 valid_len; - u8 info_type; - u8 rsvd[2]; -}; - -struct mag_port_link_param { - struct param_head head; - - u8 an; - u8 fec; - u8 speed; - u8 rsvd0; - - u32 used; - u32 an_fec_ability; - u32 an_speed_ability; - u32 an_pause_ability; -}; - -struct mag_port_wire_info { - struct param_head head; - - u8 status; - u8 rsvd0[3]; - - u8 wire_type; - u8 default_fec; - u8 speed; - u8 rsvd1; - u32 speed_ability; -}; - -struct mag_port_adapt_info { - struct param_head head; - - u32 adapt_en; - u32 flash_adapt; - u32 rsvd0[2]; - - u32 wire_node; - u32 an_en; - u32 speed; - u32 fec; -}; - -struct mag_port_param_info { - u8 parameter_cnt; - u8 lane_id; - u8 lane_num; - u8 rsvd0; - - struct mag_port_link_param default_cfg; - struct mag_port_link_param bios_cfg; - struct mag_port_link_param tool_cfg; - struct mag_port_link_param final_cfg; - - struct mag_port_wire_info wire_info; - struct mag_port_adapt_info adapt_info; -}; - -struct mag_cmd_event_port_info { - struct mgmt_msg_head head; - - u8 port_id; - u8 event_type; - u8 rsvd0[2]; - - u8 vendor_name[16]; - u32 port_type; - u32 port_sub_type; - u32 cable_length; - u8 cable_temp; - u8 max_speed; - u8 sfp_type; - u8 rsvd1; - u32 power[4]; - - u8 an_state; - u8 fec; - u16 speed; - - u8 gpio_insert; /* 0:present 1:absent */ - u8 alos; - u8 rx_los; - u8 pma_ctrl; - - u32 pma_fifo_reg; - u32 pma_signal_ok_reg; - u32 pcs_64_66b_reg; - u32 rf_lf; - u8 pcs_link; - u8 pcs_mac_link; - u8 tx_enable; - u8 rx_enable; - u32 pcs_err_cnt; - - u8 eq_data[38]; - u8 rsvd2[2]; - - u32 his_link_machine_state; - u32 cur_link_machine_state; - u8 his_machine_state_data[128]; - u8 cur_machine_state_data[128]; - u8 his_machine_state_length; - u8 cur_machine_state_length; - - struct mag_port_param_info param_info; - u8 rsvd3[360]; -}; - -struct mag_cmd_port_stats { - u64 mac_tx_fragment_pkt_num; - u64 mac_tx_undersize_pkt_num; - u64 mac_tx_undermin_pkt_num; - u64 mac_tx_64_oct_pkt_num; - u64 mac_tx_65_127_oct_pkt_num; - u64 mac_tx_128_255_oct_pkt_num; - u64 mac_tx_256_511_oct_pkt_num; - u64 mac_tx_512_1023_oct_pkt_num; - u64 mac_tx_1024_1518_oct_pkt_num; - u64 mac_tx_1519_2047_oct_pkt_num; - u64 mac_tx_2048_4095_oct_pkt_num; - u64 mac_tx_4096_8191_oct_pkt_num; - u64 mac_tx_8192_9216_oct_pkt_num; - u64 mac_tx_9217_12287_oct_pkt_num; - u64 mac_tx_12288_16383_oct_pkt_num; - u64 mac_tx_1519_max_bad_pkt_num; - u64 mac_tx_1519_max_good_pkt_num; - u64 mac_tx_oversize_pkt_num; - u64 mac_tx_jabber_pkt_num; - u64 mac_tx_bad_pkt_num; - u64 mac_tx_bad_oct_num; - u64 mac_tx_good_pkt_num; - u64 mac_tx_good_oct_num; - u64 mac_tx_total_pkt_num; - u64 mac_tx_total_oct_num; - u64 mac_tx_uni_pkt_num; - u64 mac_tx_multi_pkt_num; - u64 mac_tx_broad_pkt_num; - u64 mac_tx_pause_num; - u64 mac_tx_pfc_pkt_num; - u64 mac_tx_pfc_pri0_pkt_num; - u64 mac_tx_pfc_pri1_pkt_num; - u64 mac_tx_pfc_pri2_pkt_num; - u64 mac_tx_pfc_pri3_pkt_num; - u64 mac_tx_pfc_pri4_pkt_num; - u64 mac_tx_pfc_pri5_pkt_num; - u64 mac_tx_pfc_pri6_pkt_num; - u64 mac_tx_pfc_pri7_pkt_num; - u64 mac_tx_control_pkt_num; - u64 mac_tx_err_all_pkt_num; - u64 mac_tx_from_app_good_pkt_num; - u64 mac_tx_from_app_bad_pkt_num; - - u64 mac_rx_fragment_pkt_num; - u64 mac_rx_undersize_pkt_num; - u64 mac_rx_undermin_pkt_num; - u64 mac_rx_64_oct_pkt_num; - u64 mac_rx_65_127_oct_pkt_num; - u64 mac_rx_128_255_oct_pkt_num; - u64 mac_rx_256_511_oct_pkt_num; - u64 mac_rx_512_1023_oct_pkt_num; - u64 mac_rx_1024_1518_oct_pkt_num; - u64 mac_rx_1519_2047_oct_pkt_num; - u64 mac_rx_2048_4095_oct_pkt_num; - u64 mac_rx_4096_8191_oct_pkt_num; - u64 mac_rx_8192_9216_oct_pkt_num; - u64 mac_rx_9217_12287_oct_pkt_num; - u64 mac_rx_12288_16383_oct_pkt_num; - u64 mac_rx_1519_max_bad_pkt_num; - u64 mac_rx_1519_max_good_pkt_num; - u64 mac_rx_oversize_pkt_num; - u64 mac_rx_jabber_pkt_num; - u64 mac_rx_bad_pkt_num; - u64 mac_rx_bad_oct_num; - u64 mac_rx_good_pkt_num; - u64 mac_rx_good_oct_num; - u64 mac_rx_total_pkt_num; - u64 mac_rx_total_oct_num; - u64 mac_rx_uni_pkt_num; - u64 mac_rx_multi_pkt_num; - u64 mac_rx_broad_pkt_num; - u64 mac_rx_pause_num; - u64 mac_rx_pfc_pkt_num; - u64 mac_rx_pfc_pri0_pkt_num; - u64 mac_rx_pfc_pri1_pkt_num; - u64 mac_rx_pfc_pri2_pkt_num; - u64 mac_rx_pfc_pri3_pkt_num; - u64 mac_rx_pfc_pri4_pkt_num; - u64 mac_rx_pfc_pri5_pkt_num; - u64 mac_rx_pfc_pri6_pkt_num; - u64 mac_rx_pfc_pri7_pkt_num; - u64 mac_rx_control_pkt_num; - u64 mac_rx_sym_err_pkt_num; - u64 mac_rx_fcs_err_pkt_num; - u64 mac_rx_send_app_good_pkt_num; - u64 mac_rx_send_app_bad_pkt_num; - u64 mac_rx_unfilter_pkt_num; -}; - -struct mag_cmd_port_stats_info { - struct mgmt_msg_head head; - - u8 port_id; - u8 rsvd0[3]; -}; - -struct mag_cmd_get_port_stat { - struct mgmt_msg_head head; - - struct mag_cmd_port_stats counter; - u64 rsvd1[15]; -}; - -struct mag_cmd_clr_port_stat { - struct mgmt_msg_head head; - - u8 port_id; - u8 rsvd0[3]; -}; - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_main.c b/drivers/net/ethernet/ramaxel/spnic/spnic_main.c deleted file mode 100644 index 5b9822ebd806..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_main.c +++ /dev/null @@ -1,924 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/if_vlan.h> -#include <linux/ethtool.h> -#include <linux/dcbnl.h> -#include <linux/tcp.h> -#include <linux/ip.h> -#include <linux/debugfs.h> - -#include "sphw_common.h" -#include "sphw_hw.h" -#include "sphw_crm.h" -#include "sphw_mt.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic_io.h" -#include "spnic_nic_dev.h" -#include "spnic_tx.h" -#include "spnic_rx.h" -#include "spnic_lld.h" -#include "spnic_rss.h" -#include "spnic_dcb.h" - -#define DEFAULT_POLL_WEIGHT 64 -static unsigned int poll_weight = DEFAULT_POLL_WEIGHT; -module_param(poll_weight, uint, 0444); -MODULE_PARM_DESC(poll_weight, "Number packets for NAPI budget (default=64)"); - -#define SPNIC_DEAULT_TXRX_MSIX_PENDING_LIMIT 0 -#define SPNIC_DEAULT_TXRX_MSIX_COALESC_TIMER_CFG 0 -#define SPNIC_DEAULT_TXRX_MSIX_RESEND_TIMER_CFG 7 - -static unsigned char qp_pending_limit = SPNIC_DEAULT_TXRX_MSIX_PENDING_LIMIT; -module_param(qp_pending_limit, byte, 0444); -MODULE_PARM_DESC(qp_pending_limit, "QP MSI-X Interrupt coalescing parameter pending_limit (default=2)"); - -static unsigned char qp_coalesc_timer_cfg = - SPNIC_DEAULT_TXRX_MSIX_COALESC_TIMER_CFG; -module_param(qp_coalesc_timer_cfg, byte, 0444); -MODULE_PARM_DESC(qp_coalesc_timer_cfg, "QP MSI-X Interrupt coalescing parameter coalesc_timer_cfg (default=32)"); - -#define DEFAULT_RX_BUFF_LEN 2 -u16 rx_buff = DEFAULT_RX_BUFF_LEN; -module_param(rx_buff, ushort, 0444); -MODULE_PARM_DESC(rx_buff, "Set rx_buff size, buffer len must be 2^n. 2 - 16, default is 2KB"); - -static unsigned int lro_replenish_thld = 256; -module_param(lro_replenish_thld, uint, 0444); -MODULE_PARM_DESC(lro_replenish_thld, "Number wqe for lro replenish buffer (default=256)"); - -#define SPNIC_NIC_DEV_WQ_NAME "spnic_nic_dev_wq" - -#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_LINK) - -#define QID_MASKED(q_id, nic_dev) ((q_id) & ((nic_dev)->num_qps - 1)) -#define WATCHDOG_TIMEOUT 5 - -#define SPNIC_SQ_DEPTH 1024 -#define SPNIC_RQ_DEPTH 1024 - -enum spnic_rx_buff_len { - RX_BUFF_VALID_2KB = 2, - RX_BUFF_VALID_4KB = 4, - RX_BUFF_VALID_8KB = 8, - RX_BUFF_VALID_16KB = 16, -}; - -#define CONVERT_UNIT 1024 - -static int spnic_netdev_event(struct notifier_block *notifier, unsigned long event, void *ptr); - -/* used for netdev notifier register/unregister */ -DEFINE_MUTEX(spnic_netdev_notifiers_mutex); -static int spnic_netdev_notifiers_ref_cnt; -static struct notifier_block spnic_netdev_notifier = { - .notifier_call = spnic_netdev_event, -}; - -static void spnic_register_notifier(struct spnic_nic_dev *nic_dev) -{ - int err; - - mutex_lock(&spnic_netdev_notifiers_mutex); - spnic_netdev_notifiers_ref_cnt++; - if (spnic_netdev_notifiers_ref_cnt == 1) { - err = register_netdevice_notifier(&spnic_netdev_notifier); - if (err) { - nic_info(&nic_dev->pdev->dev, "Register netdevice notifier failed, err: %d\n", - err); - spnic_netdev_notifiers_ref_cnt--; - } - } - mutex_unlock(&spnic_netdev_notifiers_mutex); -} - -static void spnic_unregister_notifier(struct spnic_nic_dev *nic_dev) -{ - mutex_lock(&spnic_netdev_notifiers_mutex); - if (spnic_netdev_notifiers_ref_cnt == 1) - unregister_netdevice_notifier(&spnic_netdev_notifier); - - if (spnic_netdev_notifiers_ref_cnt) - spnic_netdev_notifiers_ref_cnt--; - mutex_unlock(&spnic_netdev_notifiers_mutex); -} - -#define SPNIC_MAX_VLAN_DEPTH_OFFLOAD_SUPPORT 1 -#define SPNIC_VLAN_CLEAR_OFFLOAD (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \ - NETIF_F_SCTP_CRC | NETIF_F_RXCSUM | \ - NETIF_F_ALL_TSO) - -int spnic_netdev_event(struct notifier_block *notifier, unsigned long event, void *ptr) -{ - struct net_device *ndev = netdev_notifier_info_to_dev(ptr); - struct net_device *real_dev = NULL; - struct net_device *ret = NULL; - struct spnic_nic_dev *nic_dev = NULL; - u16 vlan_depth; - - if (!is_vlan_dev(ndev)) - return NOTIFY_DONE; - - dev_hold(ndev); - - switch (event) { - case NETDEV_REGISTER: - real_dev = vlan_dev_real_dev(ndev); - nic_dev = spnic_get_uld_dev_by_ifname(real_dev->name, SERVICE_T_NIC); - if (!nic_dev) - goto out; - - vlan_depth = 1; - ret = vlan_dev_priv(ndev)->real_dev; - while (is_vlan_dev(ret)) { - ret = vlan_dev_priv(ret)->real_dev; - vlan_depth++; - } - - if (vlan_depth == SPNIC_MAX_VLAN_DEPTH_OFFLOAD_SUPPORT) { - ndev->vlan_features &= (~SPNIC_VLAN_CLEAR_OFFLOAD); - } else if (vlan_depth > SPNIC_MAX_VLAN_DEPTH_OFFLOAD_SUPPORT) { - ndev->hw_features &= (~SPNIC_VLAN_CLEAR_OFFLOAD); - ndev->features &= (~SPNIC_VLAN_CLEAR_OFFLOAD); - } - - break; - - default: - break; - }; - -out: - dev_put(ndev); - - return NOTIFY_DONE; -} - -void spnic_link_status_change(struct spnic_nic_dev *nic_dev, bool status) -{ - struct net_device *netdev = nic_dev->netdev; - - if (!SPHW_CHANNEL_RES_VALID(nic_dev) || test_bit(SPNIC_LP_TEST, &nic_dev->flags)) - return; - - if (status) { - if (netif_carrier_ok(netdev)) - return; - - nic_dev->link_status = status; - netif_carrier_on(netdev); - nicif_info(nic_dev, link, netdev, "Link is up\n"); - } else { - if (!netif_carrier_ok(netdev)) - return; - - nic_dev->link_status = status; - netif_carrier_off(netdev); - nicif_info(nic_dev, link, netdev, "Link is down\n"); - } -} - -static void netdev_feature_init(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - netdev_features_t dft_fts = 0; - netdev_features_t cso_fts = 0; - netdev_features_t vlan_fts = 0; - netdev_features_t tso_fts = 0; - netdev_features_t hw_features = 0; - - dft_fts |= NETIF_F_SG | NETIF_F_HIGHDMA; - - if (SPNIC_SUPPORT_CSUM(nic_dev->hwdev)) - cso_fts |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; - if (SPNIC_SUPPORT_SCTP_CRC(nic_dev->hwdev)) - cso_fts |= NETIF_F_SCTP_CRC; - - if (SPNIC_SUPPORT_TSO(nic_dev->hwdev)) - tso_fts |= NETIF_F_TSO | NETIF_F_TSO6; - - if (SPNIC_SUPPORT_VLAN_OFFLOAD(nic_dev->hwdev)) { - vlan_fts |= NETIF_F_HW_VLAN_CTAG_TX; - vlan_fts |= NETIF_F_HW_VLAN_CTAG_RX; - } - - if (SPNIC_SUPPORT_RXVLAN_FILTER(nic_dev->hwdev)) - vlan_fts |= NETIF_F_HW_VLAN_CTAG_FILTER; - - if (SPNIC_SUPPORT_VXLAN_OFFLOAD(nic_dev->hwdev)) - tso_fts |= NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM; - - /* LRO is disable in default, only set hw features */ - if (SPNIC_SUPPORT_LRO(nic_dev->hwdev)) - hw_features |= NETIF_F_LRO; - - netdev->features |= dft_fts | cso_fts | tso_fts | vlan_fts; - netdev->vlan_features |= dft_fts | cso_fts | tso_fts; - - hw_features |= netdev->hw_features; - - hw_features |= netdev->features; - - netdev->hw_features = hw_features; - - netdev->priv_flags |= IFF_UNICAST_FLT; - - netdev->hw_enc_features |= dft_fts; - if (SPNIC_SUPPORT_VXLAN_OFFLOAD(nic_dev->hwdev)) { - netdev->hw_enc_features |= cso_fts; - netdev->hw_enc_features |= tso_fts | NETIF_F_TSO_ECN; - } -} - -static void init_intr_coal_param(struct spnic_nic_dev *nic_dev) -{ - struct spnic_intr_coal_info *info = NULL; - u16 i; - - for (i = 0; i < nic_dev->max_qps; i++) { - info = &nic_dev->intr_coalesce[i]; - - info->pending_limt = qp_pending_limit; - info->coalesce_timer_cfg = qp_coalesc_timer_cfg; - - info->resend_timer_cfg = SPNIC_DEAULT_TXRX_MSIX_RESEND_TIMER_CFG; - - info->pkt_rate_high = SPNIC_RX_RATE_HIGH; - info->rx_usecs_high = SPNIC_RX_COAL_TIME_HIGH; - info->rx_pending_limt_high = SPNIC_RX_PENDING_LIMIT_HIGH; - info->pkt_rate_low = SPNIC_RX_RATE_LOW; - info->rx_usecs_low = SPNIC_RX_COAL_TIME_LOW; - info->rx_pending_limt_low = SPNIC_RX_PENDING_LIMIT_LOW; - } -} - -static int spnic_init_intr_coalesce(struct spnic_nic_dev *nic_dev) -{ - u64 size; - - if (qp_pending_limit != SPNIC_DEAULT_TXRX_MSIX_PENDING_LIMIT || - qp_coalesc_timer_cfg != SPNIC_DEAULT_TXRX_MSIX_COALESC_TIMER_CFG) - nic_dev->intr_coal_set_flag = 1; - else - nic_dev->intr_coal_set_flag = 0; - - size = sizeof(*nic_dev->intr_coalesce) * nic_dev->max_qps; - if (!size) { - nic_err(&nic_dev->pdev->dev, "Cannot allocate zero size intr coalesce\n"); - return -EINVAL; - } - nic_dev->intr_coalesce = kzalloc(size, GFP_KERNEL); - if (!nic_dev->intr_coalesce) { - nic_err(&nic_dev->pdev->dev, "Failed to alloc intr coalesce\n"); - return -ENOMEM; - } - - init_intr_coal_param(nic_dev); - - if (test_bit(SPNIC_INTR_ADAPT, &nic_dev->flags)) - nic_dev->adaptive_rx_coal = 1; - else - nic_dev->adaptive_rx_coal = 0; - - return 0; -} - -static void spnic_free_intr_coalesce(struct spnic_nic_dev *nic_dev) -{ - kfree(nic_dev->intr_coalesce); -} - -static int spnic_alloc_txrxqs(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - int err; - - err = spnic_alloc_txqs(netdev); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to alloc txqs\n"); - return err; - } - - err = spnic_alloc_rxqs(netdev); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to alloc rxqs\n"); - goto alloc_rxqs_err; - } - - err = spnic_init_intr_coalesce(nic_dev); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to init_intr_coalesce\n"); - goto init_intr_err; - } - - return 0; - -init_intr_err: - spnic_free_rxqs(netdev); - -alloc_rxqs_err: - spnic_free_txqs(netdev); - - return err; -} - -static void spnic_free_txrxqs(struct spnic_nic_dev *nic_dev) -{ - spnic_free_intr_coalesce(nic_dev); - spnic_free_rxqs(nic_dev->netdev); - spnic_free_txqs(nic_dev->netdev); -} - -static void spnic_sw_deinit(struct spnic_nic_dev *nic_dev) -{ - spnic_free_txrxqs(nic_dev); - - spnic_clean_mac_list_filter(nic_dev); - - spnic_del_mac(nic_dev->hwdev, nic_dev->netdev->dev_addr, 0, - sphw_global_func_id(nic_dev->hwdev), SPHW_CHANNEL_NIC); - - spnic_clear_rss_config(nic_dev); -} - -static int spnic_sw_init(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - u64 nic_feature; - int err = 0; - - nic_feature = spnic_get_feature_cap(nic_dev->hwdev); - nic_feature &= SPNIC_DRV_FEATURE; - spnic_update_nic_feature(nic_dev->hwdev, nic_feature); - - sema_init(&nic_dev->port_state_sem, 1); - - err = spnic_dcb_init(nic_dev); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to init dcb\n"); - return -EFAULT; - } - - nic_dev->q_params.sq_depth = SPNIC_SQ_DEPTH; - nic_dev->q_params.rq_depth = SPNIC_RQ_DEPTH; - - spnic_try_to_enable_rss(nic_dev); - - err = spnic_get_default_mac(nic_dev->hwdev, netdev->dev_addr); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to get MAC address\n"); - goto get_mac_err; - } - - if (!is_valid_ether_addr(netdev->dev_addr)) { - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) { - nic_err(&nic_dev->pdev->dev, "Invalid MAC address %pM\n", netdev->dev_addr); - err = -EIO; - goto err_mac; - } - - nic_info(&nic_dev->pdev->dev, "Invalid MAC address %pM, using random\n", - netdev->dev_addr); - eth_hw_addr_random(netdev); - } - - err = spnic_set_mac(nic_dev->hwdev, netdev->dev_addr, 0, - sphw_global_func_id(nic_dev->hwdev), SPHW_CHANNEL_NIC); - /* When this is VF driver, we must consider that PF has already set VF - * MAC, and we can't consider this condition is error status during - * driver probe procedure. - */ - if (err && err != SPNIC_PF_SET_VF_ALREADY) { - nic_err(&nic_dev->pdev->dev, "Failed to set default MAC\n"); - goto set_mac_err; - } - - /* MTU range: 384 - 9600 */ - netdev->min_mtu = SPNIC_MIN_MTU_SIZE; - netdev->max_mtu = SPNIC_MAX_JUMBO_FRAME_SIZE; - - err = spnic_alloc_txrxqs(nic_dev); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to alloc qps\n"); - goto alloc_qps_err; - } - - return 0; - -alloc_qps_err: - spnic_del_mac(nic_dev->hwdev, netdev->dev_addr, 0, sphw_global_func_id(nic_dev->hwdev), - SPHW_CHANNEL_NIC); - -set_mac_err: -err_mac: -get_mac_err: - spnic_clear_rss_config(nic_dev); - - return err; -} - -static void spnic_assign_netdev_ops(struct spnic_nic_dev *adapter) -{ - spnic_set_netdev_ops(adapter); - if (!SPNIC_FUNC_IS_VF(adapter->hwdev)) - spnic_set_ethtool_ops(adapter->netdev); - else - spnicvf_set_ethtool_ops(adapter->netdev); - - adapter->netdev->watchdog_timeo = WATCHDOG_TIMEOUT * HZ; -} - -static int spnic_validate_parameters(struct spnic_lld_dev *lld_dev) -{ - struct pci_dev *pdev = lld_dev->pdev; - - /* If weight exceeds the queue depth, the queue resources will be - * exhausted, and increasing it has no effect. - */ - if (!poll_weight || poll_weight > SPNIC_MAX_RX_QUEUE_DEPTH) { - nic_warn(&pdev->dev, "Module Parameter poll_weight is out of range: [1, %d], resetting to %d\n", - SPNIC_MAX_RX_QUEUE_DEPTH, DEFAULT_POLL_WEIGHT); - poll_weight = DEFAULT_POLL_WEIGHT; - } - - /* check rx_buff value, default rx_buff is 2KB. - * Valid rx_buff include 2KB/4KB/8KB/16KB. - */ - if (rx_buff != RX_BUFF_VALID_2KB && rx_buff != RX_BUFF_VALID_4KB && - rx_buff != RX_BUFF_VALID_8KB && rx_buff != RX_BUFF_VALID_16KB) { - nic_warn(&pdev->dev, "Module Parameter rx_buff value %u is out of range, must be 2^n. Valid range is 2 - 16, resetting to %dKB", - rx_buff, DEFAULT_RX_BUFF_LEN); - rx_buff = DEFAULT_RX_BUFF_LEN; - } - - return 0; -} - -static void adaptive_configuration_init(struct spnic_nic_dev *nic_dev) -{ - /* TODO: */ -} - -static int set_interrupt_moder(struct spnic_nic_dev *nic_dev, u16 q_id, - u8 coalesc_timer_cfg, u8 pending_limt) -{ - struct interrupt_info info; - int err; - - memset(&info, 0, sizeof(info)); - - if (coalesc_timer_cfg == nic_dev->rxqs[q_id].last_coalesc_timer_cfg && - pending_limt == nic_dev->rxqs[q_id].last_pending_limt) - return 0; - - /* netdev not running or qp not in using, - * don't need to set coalesce to hw - */ - if (!SPHW_CHANNEL_RES_VALID(nic_dev) || q_id >= nic_dev->q_params.num_qps) - return 0; - - info.lli_set = 0; - info.interrupt_coalesc_set = 1; - info.coalesc_timer_cfg = coalesc_timer_cfg; - info.pending_limt = pending_limt; - info.msix_index = nic_dev->q_params.irq_cfg[q_id].msix_entry_idx; - info.resend_timer_cfg = nic_dev->intr_coalesce[q_id].resend_timer_cfg; - - err = sphw_set_interrupt_cfg(nic_dev->hwdev, info, SPHW_CHANNEL_NIC); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to modify moderation for Queue: %u\n", q_id); - } else { - nic_dev->rxqs[q_id].last_coalesc_timer_cfg = coalesc_timer_cfg; - nic_dev->rxqs[q_id].last_pending_limt = pending_limt; - } - - return err; -} - -static void calc_coal_para(struct spnic_nic_dev *nic_dev, struct spnic_intr_coal_info *q_coal, - u64 rx_rate, u8 *coalesc_timer_cfg, u8 *pending_limt) -{ - if (rx_rate < q_coal->pkt_rate_low) { - *coalesc_timer_cfg = q_coal->rx_usecs_low; - *pending_limt = q_coal->rx_pending_limt_low; - } else if (rx_rate > q_coal->pkt_rate_high) { - *coalesc_timer_cfg = q_coal->rx_usecs_high; - *pending_limt = q_coal->rx_pending_limt_high; - } else { - *coalesc_timer_cfg = - (u8)((rx_rate - q_coal->pkt_rate_low) * - (q_coal->rx_usecs_high - q_coal->rx_usecs_low) / - (q_coal->pkt_rate_high - q_coal->pkt_rate_low) + q_coal->rx_usecs_low); - - *pending_limt = q_coal->rx_pending_limt_low; - } -} - -static void update_queue_coal(struct spnic_nic_dev *nic_dev, u16 qid, - u64 rx_rate, u64 avg_pkt_size, u64 tx_rate) -{ - struct spnic_intr_coal_info *q_coal = NULL; - u8 coalesc_timer_cfg, pending_limt; - - q_coal = &nic_dev->intr_coalesce[qid]; - - if (rx_rate > SPNIC_RX_RATE_THRESH && - avg_pkt_size > SPNIC_AVG_PKT_SMALL) { - calc_coal_para(nic_dev, q_coal, rx_rate, &coalesc_timer_cfg, &pending_limt); - } else { - coalesc_timer_cfg = SPNIC_LOWEST_LATENCY; - pending_limt = q_coal->rx_pending_limt_low; - } - - set_interrupt_moder(nic_dev, qid, coalesc_timer_cfg, pending_limt); -} - -void spnic_auto_moderation_work(struct work_struct *work) -{ - struct delayed_work *delay = to_delayed_work(work); - struct spnic_nic_dev *nic_dev = container_of(delay, struct spnic_nic_dev, moderation_task); - unsigned long period = (unsigned long)(jiffies - nic_dev->last_moder_jiffies); - u64 rx_packets, rx_bytes, rx_pkt_diff, rx_rate, avg_pkt_size; - u64 tx_packets, tx_bytes, tx_pkt_diff, tx_rate; - u16 qid; - - if (!test_bit(SPNIC_INTF_UP, &nic_dev->flags)) - return; - - queue_delayed_work(nic_dev->workq, &nic_dev->moderation_task, SPNIC_MODERATONE_DELAY); - - if (!nic_dev->adaptive_rx_coal || !period) - return; - - for (qid = 0; qid < nic_dev->q_params.num_qps; qid++) { - rx_packets = nic_dev->rxqs[qid].rxq_stats.packets; - rx_bytes = nic_dev->rxqs[qid].rxq_stats.bytes; - tx_packets = nic_dev->txqs[qid].txq_stats.packets; - tx_bytes = nic_dev->txqs[qid].txq_stats.bytes; - - rx_pkt_diff = rx_packets - nic_dev->rxqs[qid].last_moder_packets; - avg_pkt_size = rx_pkt_diff ? - ((unsigned long)(rx_bytes - nic_dev->rxqs[qid].last_moder_bytes)) / - rx_pkt_diff : 0; - - rx_rate = rx_pkt_diff * HZ / period; - tx_pkt_diff = tx_packets - nic_dev->txqs[qid].last_moder_packets; - tx_rate = tx_pkt_diff * HZ / period; - - update_queue_coal(nic_dev, qid, rx_rate, avg_pkt_size, tx_rate); - - nic_dev->rxqs[qid].last_moder_packets = rx_packets; - nic_dev->rxqs[qid].last_moder_bytes = rx_bytes; - nic_dev->txqs[qid].last_moder_packets = tx_packets; - nic_dev->txqs[qid].last_moder_bytes = tx_bytes; - } - - nic_dev->last_moder_jiffies = jiffies; -} - -void spnic_periodic_work_handler(struct work_struct *work) -{ - struct delayed_work *delay = to_delayed_work(work); - struct spnic_nic_dev *nic_dev = container_of(delay, struct spnic_nic_dev, periodic_work); - - if (test_and_clear_bit(EVENT_WORK_TX_TIMEOUT, &nic_dev->event_flag)) - sphw_fault_event_report(nic_dev->hwdev, SPHW_FAULT_SRC_TX_TIMEOUT, - FAULT_LEVEL_SERIOUS_FLR); - - queue_delayed_work(nic_dev->workq, &nic_dev->periodic_work, HZ); -} - -static void free_nic_dev(struct spnic_nic_dev *nic_dev) -{ - destroy_workqueue(nic_dev->workq); - kfree(nic_dev->vlan_bitmap); -} - -static int setup_nic_dev(struct net_device *netdev, struct spnic_lld_dev *lld_dev) -{ - struct pci_dev *pdev = lld_dev->pdev; - struct spnic_nic_dev *nic_dev; - u32 page_num; - - nic_dev = (struct spnic_nic_dev *)netdev_priv(netdev); - nic_dev->netdev = netdev; - SET_NETDEV_DEV(netdev, &pdev->dev); - nic_dev->hwdev = lld_dev->hwdev; - nic_dev->pdev = pdev; - nic_dev->poll_weight = (int)poll_weight; - nic_dev->msg_enable = DEFAULT_MSG_ENABLE; - nic_dev->lro_replenish_thld = lro_replenish_thld; - nic_dev->rx_buff_len = (u16)(rx_buff * CONVERT_UNIT); - nic_dev->dma_rx_buff_size = RX_BUFF_NUM_PER_PAGE * nic_dev->rx_buff_len; - page_num = nic_dev->dma_rx_buff_size / PAGE_SIZE; - nic_dev->page_order = page_num > 0 ? ilog2(page_num) : 0; - - mutex_init(&nic_dev->nic_mutex); - - nic_dev->vlan_bitmap = kzalloc(VLAN_BITMAP_SIZE(nic_dev), GFP_KERNEL); - if (!nic_dev->vlan_bitmap) { - nic_err(&pdev->dev, "Failed to allocate vlan bitmap\n"); - return -ENOMEM; - } - - nic_dev->workq = create_singlethread_workqueue(SPNIC_NIC_DEV_WQ_NAME); - if (!nic_dev->workq) { - nic_err(&pdev->dev, "Failed to initialize nic workqueue\n"); - kfree(nic_dev->vlan_bitmap); - return -ENOMEM; - } - - INIT_DELAYED_WORK(&nic_dev->periodic_work, spnic_periodic_work_handler); - - INIT_LIST_HEAD(&nic_dev->uc_filter_list); - INIT_LIST_HEAD(&nic_dev->mc_filter_list); - INIT_WORK(&nic_dev->rx_mode_work, spnic_set_rx_mode_work); - - INIT_LIST_HEAD(&nic_dev->rx_flow_rule.rules); - INIT_LIST_HEAD(&nic_dev->tcam.tcam_list); - INIT_LIST_HEAD(&nic_dev->tcam.tcam_dynamic_info.tcam_dynamic_list); - - return 0; -} - -static int spnic_set_default_hw_feature(struct spnic_nic_dev *nic_dev) -{ - int err; - - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) { - err = spnic_dcb_reset_hw_config(nic_dev); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to reset hw dcb configuration\n"); - return err; - } - } - - err = spnic_set_nic_feature_to_hw(nic_dev->hwdev); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to set nic features\n"); - return err; - } - - /* enable all hw features in netdev->features */ - return spnic_set_hw_features(nic_dev); -} - -static int nic_probe(struct spnic_lld_dev *lld_dev, void **uld_dev, char *uld_dev_name) -{ - struct pci_dev *pdev = lld_dev->pdev; - struct spnic_nic_dev *nic_dev = NULL; - struct net_device *netdev = NULL; - u16 max_qps, glb_func_id; - int err; - - /* *uld_dev should always no be NULL */ - *uld_dev = lld_dev; - - if (!sphw_support_nic(lld_dev->hwdev, NULL)) { - nic_info(&pdev->dev, "Hw don't support nic\n"); - return 0; - } - - nic_info(&pdev->dev, "NIC service probe begin\n"); - - err = spnic_validate_parameters(lld_dev); - if (err) { - err = -EINVAL; - goto err_out; - } - - glb_func_id = sphw_global_func_id(lld_dev->hwdev); - err = sphw_func_reset(lld_dev->hwdev, glb_func_id, SPHW_NIC_RES, SPHW_CHANNEL_NIC); - if (err) { - nic_err(&pdev->dev, "Failed to reset function\n"); - goto err_out; - } - - max_qps = sphw_func_max_nic_qnum(lld_dev->hwdev); - netdev = alloc_etherdev_mq(sizeof(*nic_dev), max_qps); - if (!netdev) { - nic_err(&pdev->dev, "Failed to allocate ETH device\n"); - err = -ENOMEM; - goto err_out; - } - - nic_dev = (struct spnic_nic_dev *)netdev_priv(netdev); - err = setup_nic_dev(netdev, lld_dev); - if (err) - goto setup_dev_err; - - adaptive_configuration_init(nic_dev); - - /* get nic cap from hw */ - sphw_support_nic(lld_dev->hwdev, &nic_dev->nic_cap); - - err = spnic_init_nic_hwdev(nic_dev->hwdev, pdev, &pdev->dev, nic_dev->rx_buff_len); - if (err) { - nic_err(&pdev->dev, "Failed to init nic hwdev\n"); - goto init_nic_hwdev_err; - } - - err = spnic_sw_init(nic_dev); - if (err) - goto sw_init_err; - - spnic_assign_netdev_ops(nic_dev); - netdev_feature_init(netdev); - - err = spnic_set_default_hw_feature(nic_dev); - if (err) - goto set_features_err; - - spnic_register_notifier(nic_dev); - - err = register_netdev(netdev); - if (err) { - nic_err(&pdev->dev, "Failed to register netdev\n"); - err = -ENOMEM; - goto netdev_err; - } - - queue_delayed_work(nic_dev->workq, &nic_dev->periodic_work, HZ); - netif_carrier_off(netdev); - - *uld_dev = nic_dev; - nicif_info(nic_dev, probe, netdev, "Register netdev succeed\n"); - nic_info(&pdev->dev, "NIC service probed\n"); - - return 0; - -netdev_err: - spnic_unregister_notifier(nic_dev); - -set_features_err: - spnic_sw_deinit(nic_dev); - -sw_init_err: - spnic_free_nic_hwdev(nic_dev->hwdev); - -init_nic_hwdev_err: - free_nic_dev(nic_dev); -setup_dev_err: - free_netdev(netdev); - -err_out: - nic_err(&pdev->dev, "NIC service probe failed\n"); - - return err; -} - -static void nic_remove(struct spnic_lld_dev *lld_dev, void *adapter) -{ - struct spnic_nic_dev *nic_dev = adapter; - struct net_device *netdev = NULL; - - if (!nic_dev || !sphw_support_nic(lld_dev->hwdev, NULL)) - return; - - nic_info(&lld_dev->pdev->dev, "NIC service remove begin\n"); - - netdev = nic_dev->netdev; - - unregister_netdev(netdev); - spnic_unregister_notifier(nic_dev); - - cancel_delayed_work_sync(&nic_dev->periodic_work); - cancel_work_sync(&nic_dev->rx_mode_work); - destroy_workqueue(nic_dev->workq); - - spnic_sw_deinit(nic_dev); - - spnic_flush_rx_flow_rule(nic_dev); - spnic_free_nic_hwdev(nic_dev->hwdev); - - kfree(nic_dev->vlan_bitmap); - - free_netdev(netdev); - - nic_info(&lld_dev->pdev->dev, "NIC service removed\n"); -} - -static void sriov_state_change(struct spnic_nic_dev *nic_dev, - const struct sphw_sriov_state_info *info) -{ - if (!info->enable) - spnic_clear_vfs_info(nic_dev->hwdev); -} - -const char *g_spnic_module_link_err[LINK_ERR_NUM] = { - "Unrecognized module", -}; - -void sphw_port_module_event_handler(struct spnic_nic_dev *nic_dev, struct sphw_event_info *event) -{ - enum port_module_event_type type = event->module_event.type; - enum link_err_type err_type = event->module_event.err_type; - - switch (type) { - case SPHW_PORT_MODULE_CABLE_PLUGGED: - case SPHW_PORT_MODULE_CABLE_UNPLUGGED: - nicif_info(nic_dev, link, nic_dev->netdev, - "Port module event: Cable %s\n", - type == SPHW_PORT_MODULE_CABLE_PLUGGED ? - "plugged" : "unplugged"); - break; - case SPHW_PORT_MODULE_LINK_ERR: - if (err_type >= LINK_ERR_NUM) { - nicif_info(nic_dev, link, nic_dev->netdev, - "Link failed, Unknown error type: 0x%x\n", err_type); - } else { - nicif_info(nic_dev, link, nic_dev->netdev, "Link failed, error type: 0x%x: %s\n", - err_type, g_spnic_module_link_err[err_type]); - } - break; - default: - nicif_err(nic_dev, link, nic_dev->netdev, "Unknown port module type %d\n", type); - break; - } -} - -void nic_event(struct spnic_lld_dev *lld_dev, void *adapter, struct sphw_event_info *event) -{ - struct spnic_nic_dev *nic_dev = adapter; - enum sphw_event_type type; - - if (!nic_dev || !event || !sphw_support_nic(lld_dev->hwdev, NULL)) - return; - - type = event->type; - - switch (type) { - case SPHW_EVENT_LINK_DOWN: - spnic_link_status_change(nic_dev, false); - break; - case SPHW_EVENT_LINK_UP: - spnic_link_status_change(nic_dev, true); - break; - case SPHW_EVENT_SRIOV_STATE_CHANGE: - sriov_state_change(nic_dev, &event->sriov_state); - break; - case SPHW_EVENT_PORT_MODULE_EVENT: - sphw_port_module_event_handler(nic_dev, event); - break; - case SPHW_EVENT_FAULT: - if (event->info.fault_level == FAULT_LEVEL_SERIOUS_FLR && - event->info.event.chip.func_id == sphw_global_func_id(lld_dev->hwdev)) - spnic_link_status_change(nic_dev, false); - break; - case SPHW_EVENT_PCIE_LINK_DOWN: - case SPHW_EVENT_HEART_LOST: - spnic_link_status_change(nic_dev, false); - break; - default: - break; - } -} - -struct net_device *spnic_get_netdev_by_lld(struct spnic_lld_dev *lld_dev) -{ - struct spnic_nic_dev *nic_dev = NULL; - - if (!lld_dev || !sphw_support_nic(lld_dev->hwdev, NULL)) - return NULL; - - nic_dev = spnic_get_uld_dev_by_pdev(lld_dev->pdev, SERVICE_T_NIC); - if (!nic_dev) { - sdk_err(&lld_dev->pdev->dev, - "There's no net device attached on the pci device"); - return NULL; - } - - return nic_dev->netdev; -} - -void *spnic_get_hwdev_by_netdev(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - if (!nic_dev || !netdev) - return NULL; - - return nic_dev->hwdev; -} - -struct spnic_uld_info nic_uld_info = { - .probe = nic_probe, - .remove = nic_remove, - .suspend = NULL, - .resume = NULL, - .event = nic_event, - .ioctl = nic_ioctl, -}; diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_mgmt_interface.h b/drivers/net/ethernet/ramaxel/spnic/spnic_mgmt_interface.h deleted file mode 100644 index 720f6fcf5f0a..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_mgmt_interface.h +++ /dev/null @@ -1,605 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_MGMT_INTERFACE_H -#define SPNIC_MGMT_INTERFACE_H - -#include <linux/if_ether.h> - -#include "sphw_mgmt_msg_base.h" - -#define SPNIC_CMD_OP_SET MGMT_MSG_CMD_OP_SET -#define SPNIC_CMD_OP_GET MGMT_MSG_CMD_OP_GET - -#define SPNIC_CMD_OP_ADD 1 -#define SPNIC_CMD_OP_DEL 0 - -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 NIC_F_ALL_MASK 0x3FFF - -#define NIC_MAX_FEATURE_QWORD 4 -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[NIC_MAX_FEATURE_QWORD]; -}; - -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_vport_state { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd1; - u8 state; /* 0--disable, 1--enable */ - u8 rsvd2[3]; -}; - -struct spnic_port_state { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd1; - u8 state; /* 0--disable, 1--enable */ - u8 rsvd2[3]; -}; - -struct spnic_cmd_clear_qp_resource { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd1; -}; - -struct spnic_port_stats_info { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd1; -}; - -struct spnic_vport_stats { - u64 tx_unicast_pkts_vport; - u64 tx_unicast_bytes_vport; - u64 tx_multicast_pkts_vport; - u64 tx_multicast_bytes_vport; - u64 tx_broadcast_pkts_vport; - u64 tx_broadcast_bytes_vport; - - u64 rx_unicast_pkts_vport; - u64 rx_unicast_bytes_vport; - u64 rx_multicast_pkts_vport; - u64 rx_multicast_bytes_vport; - u64 rx_broadcast_pkts_vport; - u64 rx_broadcast_bytes_vport; - - u64 tx_discard_vport; - u64 rx_discard_vport; - u64 tx_err_vport; - u64 rx_err_vport; -}; - -struct spnic_cmd_vport_stats { - struct mgmt_msg_head msg_head; - - u32 stats_size; - u32 rsvd1; - struct spnic_vport_stats stats; - u64 rsvd2[6]; -}; - -struct spnic_cmd_qpn { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 base_qpn; -}; - -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; -}; - -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_cmd_vlan_offload { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 vlan_offload; - u8 rsvd1[5]; -}; - -struct spnic_cmd_lro_config { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 opcode; - u8 rsvd1; - u8 lro_ipv4_en; - u8 lro_ipv6_en; - u8 lro_max_pkt_len; /* unit is 1K */ - u8 resv2[13]; -}; - -struct spnic_cmd_lro_timer { - struct mgmt_msg_head msg_head; - - u8 opcode; /* 1: set timer value, 0: get timer value */ - u8 rsvd1; - u16 rsvd2; - u32 timer; -}; - -struct spnic_cmd_vf_vlan_config { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 opcode; - u8 rsvd1; - u16 vlan_id; - u8 qos; - u8 rsvd2[5]; -}; - -struct spnic_cmd_spoofchk_set { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 state; - u8 rsvd1; -}; - -struct spnic_cmd_tx_rate_cfg { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd1; - u32 min_rate; - u32 max_rate; - u8 rsvd2[8]; -}; - -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_register_vf { - struct mgmt_msg_head msg_head; - - u8 op_register; /* 0 - unregister, 1 - register */ - u8 rsvd[39]; -}; - -struct spnic_cmd_link_state { - struct mgmt_msg_head msg_head; - - u8 port_id; - u8 state; - u16 rsvd1; -}; - -struct spnic_cmd_vlan_config { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 opcode; - u8 rsvd1; - u16 vlan_id; - u16 rsvd2; -}; - -/* set vlan filter */ -struct spnic_cmd_set_vlan_filter { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 resvd[2]; - u32 vlan_filter_ctrl; /* bit0:vlan filter en; bit1:broadcast_filter_en */ -}; - -struct spnic_cmd_link_ksettings_info { - struct mgmt_msg_head msg_head; - - u8 port_id; - u8 rsvd1[3]; - - u32 valid_bitmap; - u8 speed; /* enum nic_speed_level */ - u8 autoneg; /* 0 - off, 1 - on */ - u8 fec; /* 0 - RSFEC, 1 - BASEFEC, 2 - NOFEC */ - u8 rsvd2[21]; /* reserved for duplex, port, etc. */ -}; - -struct mpu_lt_info { - u8 node; - u8 inst; - u8 entry_size; - u8 rsvd; - u32 lt_index; - u32 offset; - u32 len; -}; - -struct nic_mpu_lt_opera { - struct mgmt_msg_head msg_head; - struct mpu_lt_info net_lt_cmd; - u8 data[100]; -}; - -struct spnic_rx_mode_config { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd1; - u32 rx_mode; -}; - -/* rss */ -struct spnic_rss_context_table { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd1; - u32 context; -}; - -struct spnic_cmd_rss_engine_type { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 opcode; - u8 hash_engine; - u8 rsvd1[4]; -}; - -#define SPNIC_RSS_INDIR_SIZE 256 -#define SPNIC_RSS_KEY_SIZE 40 - -struct spnic_cmd_rss_hash_key { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 opcode; - u8 rsvd1; - u8 key[SPNIC_RSS_KEY_SIZE]; -}; - -struct spnic_rss_indir_table { - struct mgmt_msg_head msg_head; - - u16 func_id; - u16 rsvd1; - u8 indir[SPNIC_RSS_INDIR_SIZE]; -}; - -#define SPNIC_DCB_UP_MAX 0x8 -#define SPNIC_DCB_COS_MAX 0x8 -#define SPNIC_DCB_TC_MAX 0x8 - -struct spnic_cmd_rss_config { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 rss_en; - u8 rq_priority_number; - u8 prio_tc[SPNIC_DCB_COS_MAX]; - u16 num_qps; - u16 rsvd1; -}; - -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_up_ets_cfg { - struct mgmt_msg_head msg_head; - - u8 port_id; - u8 rsvd1[3]; - - u8 cos_tc[SPNIC_DCB_COS_MAX]; - u8 tc_bw[SPNIC_DCB_TC_MAX]; - u8 cos_prio[SPNIC_DCB_COS_MAX]; - u8 cos_bw[SPNIC_DCB_COS_MAX]; - u8 tc_prio[SPNIC_DCB_TC_MAX]; -}; - -struct spnic_cmd_set_pfc { - struct mgmt_msg_head msg_head; - - u8 port_id; - u8 rsvd1; - u8 pfc_en; - u8 pfc_bitmap; - u8 rsvd2[4]; -}; - -struct spnic_cos_up_map { - struct mgmt_msg_head msg_head; - - u8 port_id; - /* every bit indicate index of map is valid 1 or not 0*/ - u8 cos_valid_mask; - u16 rsvd1; - - /* user priority in cos(index:cos, value: up pri) */ - u8 map[SPNIC_DCB_UP_MAX]; -}; - -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 nic_cmd_tx_pause_notice { - struct mgmt_msg_head head; - - u32 tx_pause_except; - u32 except_level; - u32 rsvd; -}; - -#define SPNIC_CMD_OP_FREE 0 -#define SPNIC_CMD_OP_ALLOC 1 - -struct spnic_cmd_cfg_qps { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 opcode; /* 1: alloc qp, 0: free qp */ - u8 rsvd1; - u16 num_qps; - u16 rsvd2; -}; - -struct spnic_cmd_led_config { - struct mgmt_msg_head msg_head; - - u8 port; - u8 type; - u8 mode; - u8 rsvd1; -}; - -struct spnic_cmd_port_loopback { - struct mgmt_msg_head msg_head; - - u8 port_id; - u8 opcode; - u8 mode; - u8 en; - u32 rsvd1[2]; -}; - -struct spnic_cmd_get_light_module_abs { - struct mgmt_msg_head msg_head; - - u8 port_id; - u8 abs_status; /* 0:present, 1:absent */ - u8 rsv[2]; -}; - -#define STD_SFP_INFO_MAX_SIZE 640 -struct spnic_cmd_get_std_sfp_info { - struct mgmt_msg_head msg_head; - - u8 port_id; - u8 wire_type; - u16 eeprom_len; - u32 rsvd; - u8 sfp_info[STD_SFP_INFO_MAX_SIZE]; -}; - -struct spnic_cable_plug_event { - struct mgmt_msg_head msg_head; - - u16 func_id; - u8 plugged; /* 0: unplugged, 1: plugged */ - u8 port_id; -}; - -struct nic_cmd_mac_info { - struct mgmt_msg_head head; - - u32 valid_bitmap; - u16 rsvd; - - u8 host_id[32]; - u8 port_id[32]; - u8 mac_addr[192]; -}; - -#define SPNIC_TCAM_BLOCK_ENABLE 1 -#define SPNIC_TCAM_BLOCK_DISABLE 0 -#define SPNIC_TCAM_BLOCK_NORMAL_TYPE 0 -#define SPNIC_MAX_TCAM_RULES_NUM 4096 - -struct nic_cmd_set_tcam_enable { - struct mgmt_msg_head head; - - u16 func_id; - u8 tcam_enable; - u8 rsvd1; - u32 rsvd2; -}; - -/* alloc tcam block input struct */ -struct nic_cmd_ctrl_tcam_block_in { - struct mgmt_msg_head head; - - u16 func_id; /* func_id */ - u8 alloc_en; /* 0: free tcam block, 1: alloc tcam block */ - u8 tcam_type; /* 0: alloc 16 size tcam block, 1: alloc 0 size tcam block */ - u16 tcam_block_index; - u16 alloc_block_num; -}; - -/* alloc tcam block output struct */ -struct nic_cmd_ctrl_tcam_block_out { - struct mgmt_msg_head head; - - u16 func_id; - u8 alloc_en; - u8 tcam_type; - u16 tcam_block_index; - u16 mpu_alloc_block_size; -}; - -struct nic_cmd_flush_tcam_rules { - struct mgmt_msg_head head; - - u16 func_id; /* func_id */ - u16 rsvd; -}; - -struct nic_cmd_dfx_fdir_tcam_block_table { - struct mgmt_msg_head head; - u8 tcam_type; - u8 valid; - u16 tcam_block_index; - u16 use_function_id; - u16 rsvd; -}; - -struct tcam_result { - u32 qid; - u32 rsvd; -}; - -#define TCAM_FLOW_KEY_SIZE 44 - -struct tcam_key_x_y { - u8 x[TCAM_FLOW_KEY_SIZE]; - u8 y[TCAM_FLOW_KEY_SIZE]; -}; - -struct nic_tcam_cfg_rule { - u32 index; - struct tcam_result data; - struct tcam_key_x_y key; -}; - -struct nic_cmd_fdir_add_rule { - struct mgmt_msg_head head; - - u16 func_id; - u16 rsvd; - struct nic_tcam_cfg_rule rule; -}; - -struct nic_cmd_fdir_del_rules { - struct mgmt_msg_head head; - - u16 func_id; - u16 rsvd; - u32 index_start; - u32 index_num; -}; - -struct nic_cmd_fdir_get_rule { - struct mgmt_msg_head head; - - u32 index; - u32 valid; - struct tcam_key_x_y key; - struct tcam_result data; - u64 packet_count; - u64 byte_count; -}; - -#endif /* SPNIC_MGMT_INTERFACE_H */ diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_netdev_ops.c b/drivers/net/ethernet/ramaxel/spnic/spnic_netdev_ops.c deleted file mode 100644 index a4f668682f37..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_netdev_ops.c +++ /dev/null @@ -1,1526 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/netlink.h> -#include <linux/debugfs.h> -#include <linux/ip.h> -#include <linux/bpf.h> - -#include "sphw_hw.h" -#include "sphw_crm.h" -#include "spnic_nic_io.h" -#include "spnic_nic_dev.h" -#include "spnic_tx.h" -#include "spnic_rx.h" -#include "spnic_dcb.h" - -#define SPNIC_DEFAULT_RX_CSUM_OFFLOAD 0xFFF - -#define SPNIC_LRO_DEFAULT_COAL_PKT_SIZE 32 -#define SPNIC_LRO_DEFAULT_TIME_LIMIT 16 -#define SPNIC_WAIT_FLUSH_QP_RESOURCE_TIMEOUT 2000 -static void spnic_nic_set_rx_mode(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - if (netdev_uc_count(netdev) != nic_dev->netdev_uc_cnt || - netdev_mc_count(netdev) != nic_dev->netdev_mc_cnt) { - set_bit(SPNIC_UPDATE_MAC_FILTER, &nic_dev->flags); - nic_dev->netdev_uc_cnt = netdev_uc_count(netdev); - nic_dev->netdev_mc_cnt = netdev_mc_count(netdev); - } - - queue_work(nic_dev->workq, &nic_dev->rx_mode_work); -} - -int spnic_alloc_txrxq_resources(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_txrxq_params *q_params) -{ - u32 size; - int err; - - size = sizeof(*q_params->txqs_res) * q_params->num_qps; - q_params->txqs_res = kzalloc(size, GFP_KERNEL); - if (!q_params->txqs_res) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc txqs resources array\n"); - return -ENOMEM; - } - - size = sizeof(*q_params->rxqs_res) * q_params->num_qps; - q_params->rxqs_res = kzalloc(size, GFP_KERNEL); - if (!q_params->rxqs_res) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc rxqs resource array\n"); - err = -ENOMEM; - goto alloc_rxqs_res_arr_err; - } - - size = sizeof(*q_params->irq_cfg) * q_params->num_qps; - q_params->irq_cfg = kzalloc(size, GFP_KERNEL); - if (!q_params->irq_cfg) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc irq resource array\n"); - err = -ENOMEM; - goto alloc_irq_cfg_err; - } - - err = spnic_alloc_txqs_res(nic_dev, q_params->num_qps, - q_params->sq_depth, q_params->txqs_res); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to alloc txqs resource\n"); - goto alloc_txqs_res_err; - } - - err = spnic_alloc_rxqs_res(nic_dev, q_params->num_qps, - q_params->rq_depth, q_params->rxqs_res); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc rxqs resource\n"); - goto alloc_rxqs_res_err; - } - - return 0; - -alloc_rxqs_res_err: - spnic_free_txqs_res(nic_dev, q_params->num_qps, q_params->sq_depth, - q_params->txqs_res); - -alloc_txqs_res_err: - kfree(q_params->irq_cfg); - q_params->irq_cfg = NULL; - -alloc_irq_cfg_err: - kfree(q_params->rxqs_res); - q_params->rxqs_res = NULL; - -alloc_rxqs_res_arr_err: - kfree(q_params->txqs_res); - q_params->txqs_res = NULL; - - return err; -} - -void spnic_free_txrxq_resources(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_txrxq_params *q_params) -{ - spnic_free_rxqs_res(nic_dev, q_params->num_qps, q_params->rq_depth, q_params->rxqs_res); - spnic_free_txqs_res(nic_dev, q_params->num_qps, q_params->sq_depth, q_params->txqs_res); - - kfree(q_params->irq_cfg); - q_params->irq_cfg = NULL; - - kfree(q_params->rxqs_res); - q_params->rxqs_res = NULL; - - kfree(q_params->txqs_res); - q_params->txqs_res = NULL; -} - -int spnic_configure_txrxqs(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_txrxq_params *q_params) -{ - int err; - - err = spnic_configure_txqs(nic_dev, q_params->num_qps, - q_params->sq_depth, q_params->txqs_res); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to configure txqs\n"); - return err; - } - - err = spnic_configure_rxqs(nic_dev, q_params->num_qps, - q_params->rq_depth, q_params->rxqs_res); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to configure rxqs\n"); - return err; - } - - return 0; -} - -static void config_dcb_qps_map(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - u8 i, num_tcs; - u16 num_rss; - - if (!test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - spnic_update_tx_db_cos(nic_dev); - return; - } - - num_tcs = (u8)netdev_get_num_tc(netdev); - /* For now, we don't support to change num_tcs */ - if (num_tcs != nic_dev->hw_dcb_cfg.max_cos || - nic_dev->q_params.num_qps < num_tcs || - !test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) { - nicif_err(nic_dev, drv, netdev, "Invalid num_tcs: %u or num_qps: %u, disable DCB\n", - num_tcs, nic_dev->q_params.num_qps); - netdev_reset_tc(netdev); - nic_dev->q_params.num_tc = 0; - clear_bit(SPNIC_DCB_ENABLE, &nic_dev->flags); - /* if we can't enable rss or get enough num_qps, - * need to sync default configure to hw - */ - spnic_configure_dcb(netdev); - } else { - /* use 0~max_cos-1 as tc for netdev */ - num_rss = nic_dev->q_params.num_rss; - for (i = 0; i < num_tcs; i++) - netdev_set_tc_queue(netdev, i, num_rss, (u16)(num_rss * i)); - } - - spnic_update_tx_db_cos(nic_dev); -} - -static int spnic_configure(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - int err; - - err = spnic_set_port_mtu(nic_dev->hwdev, (u16)netdev->mtu); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to set mtu\n"); - return err; - } - - config_dcb_qps_map(nic_dev); - - /* rx rss init */ - err = spnic_rx_configure(netdev); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to configure rx\n"); - return err; - } - - return 0; -} - -static void spnic_remove_configure(struct spnic_nic_dev *nic_dev) -{ - spnic_rx_remove_configure(nic_dev->netdev); -} - -/* try to modify the number of irq to the target number, - * and return the actual number of irq. - */ -static u16 spnic_qp_irq_change(struct spnic_nic_dev *nic_dev, u16 dst_num_qp_irq) -{ - struct irq_info *qps_irq_info = nic_dev->qps_irq_info; - u16 resp_irq_num, irq_num_gap, i; - u16 idx; - int err; - - if (dst_num_qp_irq > nic_dev->num_qp_irq) { - irq_num_gap = dst_num_qp_irq - nic_dev->num_qp_irq; - err = sphw_alloc_irqs(nic_dev->hwdev, SERVICE_T_NIC, irq_num_gap, - &qps_irq_info[nic_dev->num_qp_irq], &resp_irq_num); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc irqs\n"); - return nic_dev->num_qp_irq; - } - - nic_dev->num_qp_irq += resp_irq_num; - } else if (dst_num_qp_irq < nic_dev->num_qp_irq) { - irq_num_gap = nic_dev->num_qp_irq - dst_num_qp_irq; - for (i = 0; i < irq_num_gap; i++) { - idx = (nic_dev->num_qp_irq - i) - 1; - sphw_free_irq(nic_dev->hwdev, SERVICE_T_NIC, qps_irq_info[idx].irq_id); - qps_irq_info[idx].irq_id = 0; - qps_irq_info[idx].msix_entry_idx = 0; - } - nic_dev->num_qp_irq = dst_num_qp_irq; - } - - return nic_dev->num_qp_irq; -} - -static void config_dcb_num_qps(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_txrxq_params *q_params, - u16 max_qps) -{ - u8 num_tcs = q_params->num_tc; - u16 num_rss; - - if (!num_tcs || !test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) - return; - - if (num_tcs == nic_dev->hw_dcb_cfg.max_cos && max_qps >= num_tcs) { - num_rss = max_qps / num_tcs; - num_rss = min_t(u16, num_rss, q_params->rss_limit); - q_params->num_rss = num_rss; - q_params->num_qps = (u16)(num_tcs * num_rss); - } /* else will disable DCB in config_dcb_qps_map() */ -} - -static void spnic_config_num_qps(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_txrxq_params *q_params) -{ - u16 alloc_num_irq, cur_num_irq; - u16 dst_num_irq; - - if (test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) { - q_params->num_rss = q_params->rss_limit; - q_params->num_qps = q_params->rss_limit; - } else { - q_params->num_rss = 0; - q_params->num_qps = 1; - } - - config_dcb_num_qps(nic_dev, q_params, nic_dev->max_qps); - - if (nic_dev->num_qp_irq >= q_params->num_qps) - goto out; - - cur_num_irq = nic_dev->num_qp_irq; - - alloc_num_irq = spnic_qp_irq_change(nic_dev, q_params->num_qps); - if (alloc_num_irq < q_params->num_qps) { - q_params->num_qps = alloc_num_irq; - q_params->num_rss = q_params->num_qps; - config_dcb_num_qps(nic_dev, q_params, q_params->num_qps); - nicif_warn(nic_dev, drv, nic_dev->netdev, - "Can not get enough irqs, adjust num_qps to %u\n", - q_params->num_qps); - - /* The current irq may be in use, we must keep it */ - dst_num_irq = max_t(u16, cur_num_irq, q_params->num_qps); - spnic_qp_irq_change(nic_dev, dst_num_irq); - } - -out: - nicif_info(nic_dev, drv, nic_dev->netdev, "Finally num_qps: %u, num_rss: %u\n", - q_params->num_qps, q_params->num_rss); -} - -/* determin num_qps from rss_tmpl_id/irq_num/dcb_en */ -int spnic_setup_num_qps(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - u32 irq_size; - - nic_dev->num_qp_irq = 0; - - irq_size = sizeof(*nic_dev->qps_irq_info) * nic_dev->max_qps; - if (!irq_size) { - nicif_err(nic_dev, drv, netdev, "Cannot allocate zero size entries\n"); - return -EINVAL; - } - nic_dev->qps_irq_info = kzalloc(irq_size, GFP_KERNEL); - if (!nic_dev->qps_irq_info) { - nicif_err(nic_dev, drv, netdev, "Failed to alloc qps_irq_info\n"); - return -ENOMEM; - } - - spnic_config_num_qps(nic_dev, &nic_dev->q_params); - - return 0; -} - -static void spnic_destroy_num_qps(struct spnic_nic_dev *nic_dev) -{ - u16 i; - - for (i = 0; i < nic_dev->num_qp_irq; i++) - sphw_free_irq(nic_dev->hwdev, SERVICE_T_NIC, nic_dev->qps_irq_info[i].irq_id); - - kfree(nic_dev->qps_irq_info); -} - -int spnic_force_port_disable(struct spnic_nic_dev *nic_dev) -{ - int err; - - down(&nic_dev->port_state_sem); - - err = spnic_set_port_enable(nic_dev->hwdev, false, SPHW_CHANNEL_NIC); - if (!err) - nic_dev->force_port_disable = true; - - up(&nic_dev->port_state_sem); - - return err; -} - -int spnic_force_set_port_state(struct spnic_nic_dev *nic_dev, bool enable) -{ - int err = 0; - - down(&nic_dev->port_state_sem); - - nic_dev->force_port_disable = false; - err = spnic_set_port_enable(nic_dev->hwdev, enable, SPHW_CHANNEL_NIC); - - up(&nic_dev->port_state_sem); - - return err; -} - -int spnic_maybe_set_port_state(struct spnic_nic_dev *nic_dev, bool enable) -{ - int err; - - down(&nic_dev->port_state_sem); - - /* Do nothing when force disable - * Port will disable when call force port disable - * and should not enable port when in force mode - */ - if (nic_dev->force_port_disable) { - up(&nic_dev->port_state_sem); - return 0; - } - - err = spnic_set_port_enable(nic_dev->hwdev, enable, SPHW_CHANNEL_NIC); - - up(&nic_dev->port_state_sem); - - return err; -} - -static void spnic_print_link_message(struct spnic_nic_dev *nic_dev, u8 link_status) -{ - if (nic_dev->link_status == link_status) - return; - - nic_dev->link_status = link_status; - - nicif_info(nic_dev, link, nic_dev->netdev, "Link is %s\n", - (link_status ? "up" : "down")); -} - -int spnic_alloc_channel_resources(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_qp_params *qp_params, - struct spnic_dyna_txrxq_params *trxq_params) -{ - int err; - - qp_params->num_qps = trxq_params->num_qps; - qp_params->sq_depth = trxq_params->sq_depth; - qp_params->rq_depth = trxq_params->rq_depth; - - err = spnic_alloc_qps(nic_dev->hwdev, nic_dev->qps_irq_info, qp_params); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc qps\n"); - return err; - } - - err = spnic_alloc_txrxq_resources(nic_dev, trxq_params); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc txrxq resources\n"); - spnic_free_qps(nic_dev->hwdev, qp_params); - return err; - } - - return 0; -} - -void spnic_free_channel_resources(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_qp_params *qp_params, - struct spnic_dyna_txrxq_params *trxq_params) -{ - mutex_lock(&nic_dev->nic_mutex); - spnic_free_txrxq_resources(nic_dev, trxq_params); - spnic_free_qps(nic_dev->hwdev, qp_params); - mutex_unlock(&nic_dev->nic_mutex); -} - -int spnic_open_channel(struct spnic_nic_dev *nic_dev, struct spnic_dyna_qp_params *qp_params, - struct spnic_dyna_txrxq_params *trxq_params) -{ - int err; - - err = spnic_init_qps(nic_dev->hwdev, qp_params); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to init qps\n"); - return err; - } - - err = spnic_configure_txrxqs(nic_dev, trxq_params); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to configure txrxqs\n"); - goto cfg_txrxqs_err; - } - - err = spnic_qps_irq_init(nic_dev); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to init txrxq irq\n"); - goto init_qp_irq_err; - } - - err = spnic_configure(nic_dev); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to init txrxq irq\n"); - goto configure_err; - } - - return 0; - -configure_err: - spnic_qps_irq_deinit(nic_dev); - -init_qp_irq_err: -cfg_txrxqs_err: - spnic_deinit_qps(nic_dev->hwdev, qp_params); - - return err; -} - -void spnic_close_channel(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_qp_params *qp_params) -{ - spnic_remove_configure(nic_dev); - spnic_qps_irq_deinit(nic_dev); - spnic_deinit_qps(nic_dev->hwdev, qp_params); -} - -int spnic_vport_up(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - u8 link_status = 0; - u16 glb_func_id; - int err; - - glb_func_id = sphw_global_func_id(nic_dev->hwdev); - err = spnic_set_vport_enable(nic_dev->hwdev, glb_func_id, true, - SPHW_CHANNEL_NIC); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to enable vport\n"); - goto vport_enable_err; - } - - err = spnic_maybe_set_port_state(nic_dev, true); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to enable port\n"); - goto port_enable_err; - } - - netif_set_real_num_tx_queues(netdev, nic_dev->q_params.num_qps); - netif_set_real_num_rx_queues(netdev, nic_dev->q_params.num_qps); - netif_tx_wake_all_queues(netdev); - - err = spnic_get_link_state(nic_dev->hwdev, &link_status); - if (!err && link_status) - netif_carrier_on(netdev); - - queue_delayed_work(nic_dev->workq, &nic_dev->moderation_task, SPNIC_MODERATONE_DELAY); - - spnic_print_link_message(nic_dev, link_status); - - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) - spnic_notify_all_vfs_link_changed(nic_dev->hwdev, link_status); - - return 0; - -port_enable_err: - spnic_set_vport_enable(nic_dev->hwdev, glb_func_id, false, SPHW_CHANNEL_NIC); - -vport_enable_err: - spnic_flush_qps_res(nic_dev->hwdev); - /* After set vport disable 100ms, no packets will be send to host */ - msleep(100); - - return err; -} - -void spnic_vport_down(struct spnic_nic_dev *nic_dev) -{ - u16 glb_func_id; - - netif_carrier_off(nic_dev->netdev); - netif_tx_disable(nic_dev->netdev); - - cancel_delayed_work_sync(&nic_dev->moderation_task); - - if (sphw_get_chip_present_flag(nic_dev->hwdev)) { - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) - spnic_notify_all_vfs_link_changed(nic_dev->hwdev, 0); - - spnic_maybe_set_port_state(nic_dev, false); - - glb_func_id = sphw_global_func_id(nic_dev->hwdev); - spnic_set_vport_enable(nic_dev->hwdev, glb_func_id, false, SPHW_CHANNEL_NIC); - - spnic_flush_txqs(nic_dev->netdev); - spnic_flush_qps_res(nic_dev->hwdev); - /* After set vport disable 100ms, - * no packets will be send to host - * FPGA set 2000ms - */ - msleep(SPNIC_WAIT_FLUSH_QP_RESOURCE_TIMEOUT); - } -} - -int spnic_change_channel_settings(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_txrxq_params *trxq_params, - spnic_reopen_handler reopen_handler, const void *priv_data) -{ - struct spnic_dyna_qp_params new_qp_params = {0}; - struct spnic_dyna_qp_params cur_qp_params = {0}; - int err; - - spnic_config_num_qps(nic_dev, trxq_params); - - err = spnic_alloc_channel_resources(nic_dev, &new_qp_params, trxq_params); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to alloc channel resources\n"); - return err; - } - - if (!test_and_set_bit(SPNIC_CHANGE_RES_INVALID, &nic_dev->flags)) { - spnic_vport_down(nic_dev); - spnic_close_channel(nic_dev, &cur_qp_params); - spnic_free_channel_resources(nic_dev, &cur_qp_params, &nic_dev->q_params); - } - - if (nic_dev->num_qp_irq > trxq_params->num_qps) - spnic_qp_irq_change(nic_dev, trxq_params->num_qps); - nic_dev->q_params = *trxq_params; - - if (reopen_handler) - reopen_handler(nic_dev, priv_data); - - err = spnic_open_channel(nic_dev, &new_qp_params, trxq_params); - if (err) - goto open_channel_err; - - err = spnic_vport_up(nic_dev); - if (err) - goto vport_up_err; - - clear_bit(SPNIC_CHANGE_RES_INVALID, &nic_dev->flags); - nicif_info(nic_dev, drv, nic_dev->netdev, "Change channel settings success\n"); - - return 0; - -vport_up_err: - spnic_close_channel(nic_dev, &new_qp_params); - -open_channel_err: - spnic_free_channel_resources(nic_dev, &new_qp_params, trxq_params); - - return err; -} - -int spnic_open(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_dyna_qp_params qp_params = {0}; - int err; - - if (test_bit(SPNIC_INTF_UP, &nic_dev->flags)) { - nicif_info(nic_dev, drv, netdev, "Netdev already open, do nothing\n"); - return 0; - } - - err = spnic_init_nicio_res(nic_dev->hwdev); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to init nicio resources\n"); - return err; - } - - err = spnic_setup_num_qps(nic_dev); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to setup num_qps\n"); - goto setup_qps_err; - } - - err = spnic_alloc_channel_resources(nic_dev, &qp_params, &nic_dev->q_params); - if (err) - goto alloc_channel_res_err; - - err = spnic_open_channel(nic_dev, &qp_params, &nic_dev->q_params); - if (err) - goto open_channel_err; - - err = spnic_vport_up(nic_dev); - if (err) - goto vport_up_err; - - set_bit(SPNIC_INTF_UP, &nic_dev->flags); - nicif_info(nic_dev, drv, nic_dev->netdev, "Netdev is up\n"); - - return 0; - -vport_up_err: - spnic_close_channel(nic_dev, &qp_params); - -open_channel_err: - spnic_free_channel_resources(nic_dev, &qp_params, &nic_dev->q_params); - -alloc_channel_res_err: - spnic_destroy_num_qps(nic_dev); - -setup_qps_err: - spnic_deinit_nicio_res(nic_dev->hwdev); - - return err; -} - -int spnic_close(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_dyna_qp_params qp_params = {0}; - - if (!test_and_clear_bit(SPNIC_INTF_UP, &nic_dev->flags)) { - nicif_info(nic_dev, drv, netdev, "Netdev already close, do nothing\n"); - return 0; - } - - if (test_and_clear_bit(SPNIC_CHANGE_RES_INVALID, &nic_dev->flags)) - goto out; - - spnic_vport_down(nic_dev); - spnic_close_channel(nic_dev, &qp_params); - spnic_free_channel_resources(nic_dev, &qp_params, &nic_dev->q_params); - -out: - spnic_deinit_nicio_res(nic_dev->hwdev); - spnic_destroy_num_qps(nic_dev); - - nicif_info(nic_dev, drv, nic_dev->netdev, "Netdev is down\n"); - - return 0; -} - -#define IPV6_ADDR_LEN 4 -#define PKT_INFO_LEN 9 -#define BITS_PER_TUPLE 32 -static u32 calc_xor_rss(u8 *rss_tunple, u32 len) -{ - u32 hash_value; - u32 i; - - hash_value = rss_tunple[0]; - for (i = 1; i < len; i++) - hash_value = hash_value ^ rss_tunple[i]; - - return hash_value; -} - -static u32 calc_toep_rss(u32 *rss_tunple, u32 len, const u32 *rss_key) -{ - u32 rss = 0; - u32 i, j; - - for (i = 1; i <= len; i++) { - for (j = 0; j < BITS_PER_TUPLE; j++) - if (rss_tunple[i - 1] & ((u32)1 << - (u32)((BITS_PER_TUPLE - 1) - j))) - rss ^= (rss_key[i - 1] << j) | - (u32)((u64)rss_key[i] >> (BITS_PER_TUPLE - j)); - } - - return rss; -} - -#define RSS_VAL(val, type) \ - (((type) == SPNIC_RSS_HASH_ENGINE_TYPE_TOEP) ? ntohl(val) : (val)) - -static u8 parse_ipv6_info(struct sk_buff *skb, u32 *rss_tunple, u8 hash_engine, u32 *len) -{ - struct ipv6hdr *ipv6hdr = ipv6_hdr(skb); - u32 *saddr = (u32 *)&ipv6hdr->saddr; - u32 *daddr = (u32 *)&ipv6hdr->daddr; - u8 i; - - for (i = 0; i < IPV6_ADDR_LEN; i++) { - rss_tunple[i] = RSS_VAL(daddr[i], hash_engine); - /* The offset of the sport relative to the dport is 4 */ - rss_tunple[(u32)(i + IPV6_ADDR_LEN)] = RSS_VAL(saddr[i], hash_engine); - } - *len = IPV6_ADDR_LEN + IPV6_ADDR_LEN; - - if (skb_network_header(skb) + sizeof(*ipv6hdr) == skb_transport_header(skb)) - return ipv6hdr->nexthdr; - return 0; -} - -u16 select_queue_by_hash_func(struct net_device *dev, struct sk_buff *skb, - unsigned int num_tx_queues) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(dev); - struct nic_rss_type rss_type = nic_dev->rss_type; - struct iphdr *iphdr = NULL; - u32 rss_tunple[PKT_INFO_LEN] = {0}; - u32 len = 0; - u32 hash = 0; - u8 hash_engine = nic_dev->rss_hash_engine; - u8 l4_proto; - unsigned char *l4_hdr = NULL; - - if (skb_rx_queue_recorded(skb)) { - hash = skb_get_rx_queue(skb); - - if (unlikely(hash >= num_tx_queues)) - hash %= num_tx_queues; - return (u16)hash; - } - - iphdr = ip_hdr(skb); - if (iphdr->version == IPV4_VERSION) { - rss_tunple[len++] = RSS_VAL(iphdr->daddr, hash_engine); - rss_tunple[len++] = RSS_VAL(iphdr->saddr, hash_engine); - l4_proto = iphdr->protocol; - } else if (iphdr->version == IPV6_VERSION) { - l4_proto = parse_ipv6_info(skb, (u32 *)rss_tunple, hash_engine, &len); - } else { - return (u16)hash; - } - - if ((iphdr->version == IPV4_VERSION && - ((l4_proto == IPPROTO_UDP && rss_type.udp_ipv4) || - (l4_proto == IPPROTO_TCP && rss_type.tcp_ipv4))) || - (iphdr->version == IPV6_VERSION && - ((l4_proto == IPPROTO_UDP && rss_type.udp_ipv6) || - (l4_proto == IPPROTO_TCP && rss_type.tcp_ipv6)))) { - l4_hdr = skb_transport_header(skb); - /* High 16 bits are dport, low 16 bits are sport. */ - rss_tunple[len++] = ((u32)ntohs(*((u16 *)l4_hdr + 1U)) << 16) | - ntohs(*(u16 *)l4_hdr); - } /* rss_type.ipv4 and rss_type.ipv6 default on. */ - - if (hash_engine == SPNIC_RSS_HASH_ENGINE_TYPE_TOEP) - hash = calc_toep_rss((u32 *)rss_tunple, len, nic_dev->rss_hkey_be); - else - hash = calc_xor_rss((u8 *)rss_tunple, len * (u32)sizeof(u32)); - - return (u16)nic_dev->rss_indir[hash & 0xFF]; -} - -static u16 spnic_select_queue(struct net_device *netdev, struct sk_buff *skb, - struct net_device *sb_dev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - if (skb->vlan_tci) - skb->priority = skb->vlan_tci >> VLAN_PRIO_SHIFT; - - if (netdev_get_num_tc(netdev)) - goto fall_back; - - if (test_bit(SPNIC_SAME_RXTX, &nic_dev->flags)) - return select_queue_by_hash_func(netdev, skb, netdev->real_num_tx_queues); - -fall_back: - return netdev_pick_tx(netdev, skb, NULL); -} - -static void spnic_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) - -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_txq_stats *txq_stats = NULL; - struct spnic_rxq_stats *rxq_stats = NULL; - struct spnic_txq *txq = NULL; - struct spnic_rxq *rxq = NULL; - u64 bytes, packets, dropped, errors; - unsigned int start; - int i; - - bytes = 0; - packets = 0; - dropped = 0; - for (i = 0; i < nic_dev->max_qps; i++) { - if (!nic_dev->txqs) - break; - - txq = &nic_dev->txqs[i]; - txq_stats = &txq->txq_stats; - do { - start = u64_stats_fetch_begin(&txq_stats->syncp); - bytes += txq_stats->bytes; - packets += txq_stats->packets; - dropped += txq_stats->dropped; - } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); - } - stats->tx_packets = packets; - stats->tx_bytes = bytes; - stats->tx_dropped = dropped; - - bytes = 0; - packets = 0; - errors = 0; - dropped = 0; - for (i = 0; i < nic_dev->max_qps; i++) { - if (!nic_dev->rxqs) - break; - - rxq = &nic_dev->rxqs[i]; - rxq_stats = &rxq->rxq_stats; - do { - start = u64_stats_fetch_begin(&rxq_stats->syncp); - bytes += rxq_stats->bytes; - packets += rxq_stats->packets; - errors += rxq_stats->csum_errors + rxq_stats->other_errors; - dropped += rxq_stats->dropped; - } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); - } - stats->rx_packets = packets; - stats->rx_bytes = bytes; - stats->rx_errors = errors; - stats->rx_dropped = dropped; -} - -static void spnic_tx_timeout(struct net_device *netdev, unsigned int txqueue) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_io_queue *sq = NULL; - bool hw_err = false; - u32 sw_pi, hw_ci; - u8 q_id; - - SPNIC_NIC_STATS_INC(nic_dev, netdev_tx_timeout); - nicif_err(nic_dev, drv, netdev, "Tx timeout\n"); - - for (q_id = 0; q_id < nic_dev->q_params.num_qps; q_id++) { - if (!netif_xmit_stopped(netdev_get_tx_queue(netdev, q_id))) - continue; - - sq = nic_dev->txqs[q_id].sq; - sw_pi = spnic_get_sq_local_pi(sq); - hw_ci = spnic_get_sq_hw_ci(sq); - nicif_info(nic_dev, drv, netdev, "txq%u: sw_pi: %hu, hw_ci: %u, sw_ci: %u, napi->state: 0x%lx\n", - q_id, sw_pi, hw_ci, spnic_get_sq_local_ci(sq), - nic_dev->q_params.irq_cfg[q_id].napi.state); - - if (sw_pi != hw_ci) - hw_err = true; - } - - if (hw_err) - set_bit(EVENT_WORK_TX_TIMEOUT, &nic_dev->event_flag); -} - -static int spnic_change_mtu(struct net_device *netdev, int new_mtu) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u32 mtu = (u32)new_mtu; - int err = 0; - - u32 xdp_max_mtu; - - if (spnic_is_xdp_enable(nic_dev)) { - xdp_max_mtu = spnic_xdp_max_mtu(nic_dev); - if (mtu > xdp_max_mtu) { - nicif_err(nic_dev, drv, netdev, "Max MTU for xdp usage is %d\n", - xdp_max_mtu); - return -EINVAL; - } - } - - err = spnic_set_port_mtu(nic_dev->hwdev, (u16)mtu); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to change port mtu to %d\n", - new_mtu); - } else { - nicif_info(nic_dev, drv, nic_dev->netdev, "Change mtu from %u to %d\n", - netdev->mtu, new_mtu); - netdev->mtu = mtu; - } - - return err; -} - -static int spnic_set_mac_addr(struct net_device *netdev, void *addr) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct sockaddr *saddr = addr; - int err; - - if (!is_valid_ether_addr(saddr->sa_data)) - return -EADDRNOTAVAIL; - - if (ether_addr_equal(netdev->dev_addr, saddr->sa_data)) { - nicif_info(nic_dev, drv, netdev, "Already using mac address %pM\n", - saddr->sa_data); - return 0; - } - - err = spnic_update_mac(nic_dev->hwdev, netdev->dev_addr, saddr->sa_data, 0, - sphw_global_func_id(nic_dev->hwdev)); - if (err) - return err; - - ether_addr_copy(netdev->dev_addr, saddr->sa_data); - - nicif_info(nic_dev, drv, netdev, "Set new mac address %pM\n", saddr->sa_data); - - return 0; -} - -static int spnic_vlan_rx_add_vid(struct net_device *netdev, __always_unused __be16 proto, u16 vid) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - unsigned long *vlan_bitmap = nic_dev->vlan_bitmap; - u16 func_id; - u32 col, line; - int err = 0; - - /* VLAN 0 donot be added, which is the same as VLAN 0 deleted. */ - if (vid == 0) - goto end; - - col = VID_COL(nic_dev, vid); - line = VID_LINE(nic_dev, vid); - - func_id = sphw_global_func_id(nic_dev->hwdev); - - err = spnic_add_vlan(nic_dev->hwdev, vid, func_id); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to add vlan %u\n", vid); - goto end; - } - - set_bit(col, &vlan_bitmap[line]); - - nicif_info(nic_dev, drv, netdev, "Add vlan %u\n", vid); - -end: - return err; -} - -static int spnic_vlan_rx_kill_vid(struct net_device *netdev, __always_unused __be16 proto, u16 vid) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - unsigned long *vlan_bitmap = nic_dev->vlan_bitmap; - u16 func_id; - int col, line; - int err = 0; - - col = VID_COL(nic_dev, vid); - line = VID_LINE(nic_dev, vid); - - /* In the broadcast scenario, ucode finds the corresponding function - * based on VLAN 0 of vlan table. If we delete VLAN 0, the VLAN function - * is affected. - */ - if (vid == 0) - goto end; - - func_id = sphw_global_func_id(nic_dev->hwdev); - err = spnic_del_vlan(nic_dev->hwdev, vid, func_id); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to delete vlan\n"); - goto end; - } - - clear_bit(col, &vlan_bitmap[line]); - - nicif_info(nic_dev, drv, netdev, "Remove vlan %u\n", vid); - -end: - return err; -} - -#define SET_FEATURES_OP_STR(op) ((op) ? "Enable" : "Disable") - -static int set_feature_rx_csum(struct spnic_nic_dev *nic_dev, netdev_features_t wanted_features, - netdev_features_t features, netdev_features_t *failed_features) -{ - netdev_features_t changed = wanted_features ^ features; - - if (changed & NETIF_F_RXCSUM) - spnic_info(nic_dev, drv, "%s rx csum success\n", - SET_FEATURES_OP_STR(wanted_features & NETIF_F_RXCSUM)); - - return 0; -} - -static int set_feature_tso(struct spnic_nic_dev *nic_dev, netdev_features_t wanted_features, - netdev_features_t features, netdev_features_t *failed_features) -{ - netdev_features_t changed = wanted_features ^ features; - - if (changed & NETIF_F_TSO) - spnic_info(nic_dev, drv, "%s tso success\n", - SET_FEATURES_OP_STR(wanted_features & NETIF_F_TSO)); - - return 0; -} - -static int set_feature_lro(struct spnic_nic_dev *nic_dev, netdev_features_t wanted_features, - netdev_features_t features, netdev_features_t *failed_features) -{ - netdev_features_t changed = wanted_features ^ features; - bool en = !!(wanted_features & NETIF_F_LRO); - int err; - - if (!(changed & NETIF_F_LRO)) - return 0; - - if (en && spnic_is_xdp_enable(nic_dev)) { - spnic_err(nic_dev, drv, "Can not enable LRO when xdp is enable\n"); - *failed_features |= NETIF_F_LRO; - return -EINVAL; - } - - err = spnic_set_rx_lro_state(nic_dev->hwdev, en, SPNIC_LRO_DEFAULT_TIME_LIMIT, - SPNIC_LRO_DEFAULT_COAL_PKT_SIZE); - if (err) { - spnic_err(nic_dev, drv, "%s lro failed\n", SET_FEATURES_OP_STR(en)); - *failed_features |= NETIF_F_LRO; - } else { - spnic_info(nic_dev, drv, "%s lro success\n", SET_FEATURES_OP_STR(en)); - } - - return err; -} - -static int set_feature_rx_cvlan(struct spnic_nic_dev *nic_dev, netdev_features_t wanted_features, - netdev_features_t features, netdev_features_t *failed_features) -{ - netdev_features_t changed = wanted_features ^ features; - netdev_features_t vlan_feature = NETIF_F_HW_VLAN_CTAG_RX; - bool en = !!(wanted_features & vlan_feature); - int err; - - if (!(changed & vlan_feature)) - return 0; - - err = spnic_set_rx_vlan_offload(nic_dev->hwdev, en); - if (err) { - spnic_err(nic_dev, drv, "%s rxvlan failed\n", SET_FEATURES_OP_STR(en)); - *failed_features |= vlan_feature; - } else { - spnic_info(nic_dev, drv, "%s rxvlan success\n", SET_FEATURES_OP_STR(en)); - } - - return err; -} - -static int set_feature_vlan_filter(struct spnic_nic_dev *nic_dev, netdev_features_t wanted_features, - netdev_features_t features, netdev_features_t *failed_features) -{ - netdev_features_t changed = wanted_features ^ features; - netdev_features_t vlan_filter_feature = NETIF_F_HW_VLAN_CTAG_FILTER; - bool en = !!(wanted_features & vlan_filter_feature); - int err = 0; - - if (!(changed & vlan_filter_feature)) - return 0; - - if (err == 0) - err = spnic_set_vlan_fliter(nic_dev->hwdev, en); - if (err) { - spnic_err(nic_dev, drv, "%s rx vlan filter failed\n", SET_FEATURES_OP_STR(en)); - *failed_features |= vlan_filter_feature; - } else { - spnic_info(nic_dev, drv, "%s rx vlan filter success\n", SET_FEATURES_OP_STR(en)); - } - - return err; -} - -static int set_features(struct spnic_nic_dev *nic_dev, netdev_features_t pre_features, - netdev_features_t features) -{ - netdev_features_t failed_features = 0; - u32 err = 0; - - err |= (u32)set_feature_rx_csum(nic_dev, features, pre_features, &failed_features); - err |= (u32)set_feature_tso(nic_dev, features, pre_features, &failed_features); - err |= (u32)set_feature_lro(nic_dev, features, pre_features, &failed_features); - err |= (u32)set_feature_rx_cvlan(nic_dev, features, pre_features, &failed_features); - err |= (u32)set_feature_vlan_filter(nic_dev, features, pre_features, &failed_features); - if (err) { - nic_dev->netdev->features = features ^ failed_features; - return -EIO; - } - - return 0; -} - -static int spnic_set_features(struct net_device *netdev, netdev_features_t features) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - return set_features(nic_dev, nic_dev->netdev->features, features); -} - -int spnic_set_hw_features(struct spnic_nic_dev *nic_dev) -{ - /* enable all hw features in netdev->features */ - return set_features(nic_dev, ~nic_dev->netdev->features, nic_dev->netdev->features); -} - -static netdev_features_t spnic_fix_features(struct net_device *netdev, netdev_features_t features) -{ - /* If Rx checksum is disabled, then LRO should also be disabled */ - if (!(features & NETIF_F_RXCSUM)) - features &= ~NETIF_F_LRO; - - return features; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void spnic_netpoll(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u16 i; - - for (i = 0; i < nic_dev->q_params.num_qps; i++) - napi_schedule(&nic_dev->q_params.irq_cfg[i].napi); -} -#endif /* CONFIG_NET_POLL_CONTROLLER */ - -static int spnic_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) -{ - struct spnic_nic_dev *adapter = netdev_priv(netdev); - int err; - - if (is_multicast_ether_addr(mac) || vf >= pci_num_vf(adapter->pdev)) - return -EINVAL; - - err = spnic_set_vf_mac(adapter->hwdev, OS_VF_ID_TO_HW(vf), mac); - if (err) - return err; - - if (!is_zero_ether_addr(mac)) - nic_info(&adapter->pdev->dev, "Setting MAC %pM on VF %d\n", mac, vf); - else - nic_info(&adapter->pdev->dev, "Deleting MAC on VF %d\n", vf); - - nic_info(&adapter->pdev->dev, "Please reload the VF driver to make this change effective."); - - return 0; -} - -static int set_hw_vf_vlan(void *hwdev, u16 cur_vlanprio, int vf, u16 vlan, u8 qos) -{ - int err = 0; - u16 old_vlan = cur_vlanprio & VLAN_VID_MASK; - - if (vlan || qos) { - if (cur_vlanprio) { - err = spnic_kill_vf_vlan(hwdev, OS_VF_ID_TO_HW(vf)); - if (err) - return err; - } - err = spnic_add_vf_vlan(hwdev, OS_VF_ID_TO_HW(vf), vlan, qos); - } else { - err = spnic_kill_vf_vlan(hwdev, OS_VF_ID_TO_HW(vf)); - } - - if (err) - return err; - - return spnic_update_mac_vlan(hwdev, old_vlan, vlan, OS_VF_ID_TO_HW(vf)); -} - -#define SPNIC_MAX_VLAN_ID 4094 -#define SPNIC_MAX_QOS_NUM 7 - -static int spnic_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, - u8 qos, __be16 vlan_proto) -{ - struct spnic_nic_dev *adapter = netdev_priv(netdev); - u16 vlanprio, cur_vlanprio; - - if (vf >= pci_num_vf(adapter->pdev) || vlan > SPNIC_MAX_VLAN_ID || qos > SPNIC_MAX_QOS_NUM) - return -EINVAL; - if (vlan_proto != htons(ETH_P_8021Q)) - return -EPROTONOSUPPORT; - vlanprio = vlan | qos << SPNIC_VLAN_PRIORITY_SHIFT; - cur_vlanprio = spnic_vf_info_vlanprio(adapter->hwdev, OS_VF_ID_TO_HW(vf)); - /* duplicate request, so just return success */ - if (vlanprio == cur_vlanprio) - return 0; - - return set_hw_vf_vlan(adapter->hwdev, cur_vlanprio, vf, vlan, qos); -} - -static int spnic_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting) -{ - struct spnic_nic_dev *adapter = netdev_priv(netdev); - int err = 0; - bool cur_spoofchk = false; - - if (vf >= pci_num_vf(adapter->pdev)) - return -EINVAL; - - cur_spoofchk = spnic_vf_info_spoofchk(adapter->hwdev, OS_VF_ID_TO_HW(vf)); - /* same request, so just return success */ - if ((setting && cur_spoofchk) || (!setting && !cur_spoofchk)) - return 0; - - err = spnic_set_vf_spoofchk(adapter->hwdev, OS_VF_ID_TO_HW(vf), setting); - if (!err) - nicif_info(adapter, drv, netdev, "Set VF %d spoofchk %s\n", - vf, setting ? "on" : "off"); - - return err; -} - -int spnic_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting) -{ - struct spnic_nic_dev *adapter = netdev_priv(netdev); - int err; - bool cur_trust; - - if (vf >= pci_num_vf(adapter->pdev)) - return -EINVAL; - - cur_trust = spnic_get_vf_trust(adapter->hwdev, OS_VF_ID_TO_HW(vf)); - /* same request, so just return success */ - if ((setting && cur_trust) || (!setting && !cur_trust)) - return 0; - - err = spnic_set_vf_trust(adapter->hwdev, OS_VF_ID_TO_HW(vf), setting); - if (!err) - nicif_info(adapter, drv, netdev, "Set VF %d trusted %s successfully\n", - vf, setting ? "on" : "off"); - else - nicif_err(adapter, drv, netdev, "Failed set VF %d trusted %s\n", - vf, setting ? "on" : "off"); - - return err; -} - -static int spnic_ndo_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *ivi) -{ - struct spnic_nic_dev *adapter = netdev_priv(netdev); - - if (vf >= pci_num_vf(adapter->pdev)) - return -EINVAL; - - spnic_get_vf_config(adapter->hwdev, OS_VF_ID_TO_HW(vf), ivi); - - return 0; -} - -/** - * spnic_ndo_set_vf_link_state - * @netdev: network interface device structure - * @vf_id: VF identifier - * @link: required link state - * - * Set the link state of a specified VF, regardless of physical link state - **/ -int spnic_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link) -{ - static const char * const vf_link[] = {"auto", "enable", "disable"}; - struct spnic_nic_dev *adapter = netdev_priv(netdev); - int err; - - /* validate the request */ - if (vf_id >= pci_num_vf(adapter->pdev)) { - nicif_err(adapter, drv, netdev, "Invalid VF Identifier %d\n", vf_id); - return -EINVAL; - } - - err = spnic_set_vf_link_state(adapter->hwdev, OS_VF_ID_TO_HW(vf_id), link); - if (!err) - nicif_info(adapter, drv, netdev, "Set VF %d link state: %s\n", - vf_id, vf_link[link]); - - return err; -} - -static int is_set_vf_bw_param_valid(const struct spnic_nic_dev *adapter, - int vf, int min_tx_rate, int max_tx_rate) -{ - /* verify VF is active */ - if (vf >= pci_num_vf(adapter->pdev)) { - nicif_err(adapter, drv, adapter->netdev, "VF number must be less than %d\n", - pci_num_vf(adapter->pdev)); - return -EINVAL; - } - - if (max_tx_rate < min_tx_rate) { - nicif_err(adapter, drv, adapter->netdev, "Invalid rate, max rate %d must greater than min rate %d\n", - max_tx_rate, min_tx_rate); - return -EINVAL; - } - - return 0; -} - -#define SPNIC_TX_RATE_TABLE_FULL 12 - -static int spnic_ndo_set_vf_bw(struct net_device *netdev, int vf, int min_tx_rate, int max_tx_rate) -{ - struct spnic_nic_dev *adapter = netdev_priv(netdev); - struct nic_port_info port_info = {0}; - u8 link_status = 0; - u32 speeds[] = {0, SPEED_10, SPEED_100, SPEED_1000, SPEED_10000, - SPEED_25000, SPEED_40000, SPEED_50000, SPEED_100000, - SPEED_200000}; - int err = 0; - - err = is_set_vf_bw_param_valid(adapter, vf, min_tx_rate, max_tx_rate); - if (err) - return err; - - err = spnic_get_link_state(adapter->hwdev, &link_status); - if (err) { - nicif_err(adapter, drv, netdev, "Get link status failed when set vf tx rate\n"); - return -EIO; - } - - if (!link_status) { - nicif_err(adapter, drv, netdev, "Link status must be up when set vf tx rate\n"); - return -EINVAL; - } - - err = spnic_get_port_info(adapter->hwdev, &port_info, SPHW_CHANNEL_NIC); - if (err || port_info.speed >= PORT_SPEED_UNKNOWN) - return -EIO; - - /* rate limit cannot be less than 0 and greater than link speed */ - if (max_tx_rate < 0 || max_tx_rate > speeds[port_info.speed]) { - nicif_err(adapter, drv, netdev, "Set vf max tx rate must be in [0 - %u]\n", - speeds[port_info.speed]); - return -EINVAL; - } - - err = spnic_set_vf_tx_rate(adapter->hwdev, OS_VF_ID_TO_HW(vf), max_tx_rate, min_tx_rate); - if (err) { - nicif_err(adapter, drv, netdev, "Unable to set VF %d max rate %d min rate %d%s\n", - vf, max_tx_rate, min_tx_rate, - err == SPNIC_TX_RATE_TABLE_FULL ? ", tx rate profile is full" : ""); - return -EIO; - } - - nicif_info(adapter, drv, netdev, "Set VF %d max tx rate %d min tx rate %d successfully\n", - vf, max_tx_rate, min_tx_rate); - - return 0; -} - -bool spnic_is_xdp_enable(struct spnic_nic_dev *nic_dev) -{ - return !!nic_dev->xdp_prog; -} - -int spnic_xdp_max_mtu(struct spnic_nic_dev *nic_dev) -{ - return nic_dev->rx_buff_len - (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN); -} - -static int spnic_xdp_setup(struct spnic_nic_dev *nic_dev, struct bpf_prog *prog, - struct netlink_ext_ack *extack) -{ - struct bpf_prog *old_prog = NULL; - int max_mtu = spnic_xdp_max_mtu(nic_dev); - int q_id; - - if (nic_dev->netdev->mtu > max_mtu) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to setup xdp program, the current MTU %d is larger than max allowed MTU %d\n", - nic_dev->netdev->mtu, max_mtu); - NL_SET_ERR_MSG_MOD(extack, "MTU too large for loading xdp program"); - return -EINVAL; - } - - if (nic_dev->netdev->features & NETIF_F_LRO) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to setup xdp program while LRO is on\n"); - NL_SET_ERR_MSG_MOD(extack, "Failed to setup xdp program while LRO is on\n"); - return -EINVAL; - } - - old_prog = xchg(&nic_dev->xdp_prog, prog); - for (q_id = 0; q_id < nic_dev->max_qps; q_id++) - xchg(&nic_dev->rxqs[q_id].xdp_prog, nic_dev->xdp_prog); - - if (old_prog) - bpf_prog_put(old_prog); - - return 0; -} - -static int spnic_xdp(struct net_device *netdev, struct netdev_bpf *xdp) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - switch (xdp->command) { - case XDP_SETUP_PROG: - return spnic_xdp_setup(nic_dev, xdp->prog, xdp->extack); - default: - return -EINVAL; - } -} - -static const struct net_device_ops spnic_netdev_ops = { - .ndo_open = spnic_open, - .ndo_stop = spnic_close, - .ndo_start_xmit = spnic_xmit_frame, - - .ndo_get_stats64 = spnic_get_stats64, - - .ndo_tx_timeout = spnic_tx_timeout, - .ndo_select_queue = spnic_select_queue, - .ndo_change_mtu = spnic_change_mtu, - .ndo_set_mac_address = spnic_set_mac_addr, - .ndo_validate_addr = eth_validate_addr, - - .ndo_vlan_rx_add_vid = spnic_vlan_rx_add_vid, - .ndo_vlan_rx_kill_vid = spnic_vlan_rx_kill_vid, - - .ndo_set_vf_mac = spnic_ndo_set_vf_mac, - .ndo_set_vf_vlan = spnic_ndo_set_vf_vlan, - .ndo_set_vf_rate = spnic_ndo_set_vf_bw, - .ndo_set_vf_spoofchk = spnic_ndo_set_vf_spoofchk, - - .ndo_set_vf_trust = spnic_ndo_set_vf_trust, - - .ndo_get_vf_config = spnic_ndo_get_vf_config, - -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = spnic_netpoll, -#endif /* CONFIG_NET_POLL_CONTROLLER */ - - .ndo_set_rx_mode = spnic_nic_set_rx_mode, - - .ndo_bpf = spnic_xdp, - - .ndo_set_vf_link_state = spnic_ndo_set_vf_link_state, - - .ndo_fix_features = spnic_fix_features, - .ndo_set_features = spnic_set_features, -}; - -static const struct net_device_ops spnicvf_netdev_ops = { - .ndo_open = spnic_open, - .ndo_stop = spnic_close, - .ndo_start_xmit = spnic_xmit_frame, - - .ndo_get_stats64 = spnic_get_stats64, - - .ndo_tx_timeout = spnic_tx_timeout, - .ndo_select_queue = spnic_select_queue, - - .ndo_change_mtu = spnic_change_mtu, - .ndo_set_mac_address = spnic_set_mac_addr, - .ndo_validate_addr = eth_validate_addr, - - .ndo_vlan_rx_add_vid = spnic_vlan_rx_add_vid, - .ndo_vlan_rx_kill_vid = spnic_vlan_rx_kill_vid, - -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = spnic_netpoll, -#endif /* CONFIG_NET_POLL_CONTROLLER */ - - .ndo_set_rx_mode = spnic_nic_set_rx_mode, - - .ndo_bpf = spnic_xdp, - - .ndo_fix_features = spnic_fix_features, - .ndo_set_features = spnic_set_features, -}; - -void spnic_set_netdev_ops(struct spnic_nic_dev *nic_dev) -{ - if (!SPNIC_FUNC_IS_VF(nic_dev->hwdev)) - nic_dev->netdev->netdev_ops = &spnic_netdev_ops; - else - nic_dev->netdev->netdev_ops = &spnicvf_netdev_ops; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic.h b/drivers/net/ethernet/ramaxel/spnic/spnic_nic.h deleted file mode 100644 index 83c904bc0f72..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic.h +++ /dev/null @@ -1,148 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_NIC_H -#define SPNIC_NIC_H -#include <linux/types.h> -#include "sphw_common.h" -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_mag_cmd.h" - -#define MSG_TO_MGMT_SYNC_RETURN_ERR(err, status, out_size) \ - ((err) || (status) || !(out_size)) - -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 vf_data_storage { - u8 drv_mac_addr[ETH_ALEN]; - u8 user_mac_addr[ETH_ALEN]; - bool registered; - bool use_specified_mac; - u16 pf_vlan; - u8 pf_qos; - u32 max_rate; - u32 min_rate; - - bool link_forced; - bool link_up; /* only valid if VF link is forced */ - bool spoofchk; - bool trust; - u16 num_qps; -}; - -struct spnic_port_routine_cmd { - bool mpu_send_sfp_info; - bool mpu_send_sfp_abs; - - struct mag_cmd_get_xsfp_info std_sfp_info; - struct mag_cmd_get_xsfp_present abs; -}; - -struct spnic_nic_cfg { - void *hwdev; - void *pcidev_hdl; - void *dev_hdl; - - struct spnic_io_queue *sq; - struct spnic_io_queue *rq; - - u16 rx_buff_len; - - u16 num_qps; - u16 max_qps; - - void *ci_vaddr_base; - dma_addr_t ci_dma_base; - - /* including rq and rx doorbell */ - u16 allocated_num_db; - u8 __iomem **db_addr; - - u8 link_status; - - u16 max_vfs; - struct vf_data_storage *vf_infos; - struct spnic_dcb_state dcb_state; - - u64 feature_cap; - - struct semaphore cfg_lock; - - /* Valid when pfc is disable */ - bool pause_set; - struct nic_pause_config nic_pause; - - u8 pfc_en; - u8 pfc_bitmap; - - struct nic_port_info port_info; - - /* percentage of pf link bandwidth */ - u32 pf_bw_limit; - - struct spnic_port_routine_cmd rt_cmd; - /* mutex used for copy sfp info */ - struct mutex sfp_mutex; -}; - -struct vf_msg_handler { - u16 cmd; - int (*handler)(struct spnic_nic_cfg *nic_cfg, u16 vf, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size); -}; - -struct nic_event_handler { - u16 cmd; - void (*handler)(void *hwdev, void *buf_in, u16 in_size, void *buf_out, u16 *out_size); -}; - -int spnic_set_ci_table(void *hwdev, struct spnic_sq_attr *attr); - -int l2nic_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_ch(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u16 channel); - -int spnic_cfg_vf_vlan(struct spnic_nic_cfg *nic_cfg, u8 opcode, u16 vid, u8 qos, int vf_id); - -int spnic_vf_event_handler(void *hwdev, void *pri_handle, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size); - -void spnic_pf_event_handler(void *hwdev, void *pri_handle, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size); - -int spnic_pf_mbox_handler(void *hwdev, void *pri_handle, u16 vf_id, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size); - -u8 spnic_nic_sw_aeqe_handler(void *hwdev, u8 event, u8 *data); - -int spnic_vf_func_init(struct spnic_nic_cfg *nic_cfg); - -void spnic_vf_func_free(struct spnic_nic_cfg *nic_cfg); - -void spnic_notify_dcb_state_event(struct spnic_nic_cfg *nic_cfg, struct spnic_dcb_state *dcb_state); - -int spnic_save_dcb_state(struct spnic_nic_cfg *nic_cfg, struct spnic_dcb_state *dcb_state); - -void spnic_notify_vf_link_status(struct spnic_nic_cfg *nic_cfg, u16 vf_id, u8 link_status); - -int spnic_vf_mag_event_handler(void *hwdev, void *pri_handle, u16 cmd, - void *buf_in, u16 in_size, void *buf_out, u16 *out_size); - -void spnic_pf_mag_event_handler(void *hwdev, void *pri_handle, u16 cmd, - void *buf_in, u16 in_size, void *buf_out, u16 *out_size); - -int spnic_pf_mag_mbox_handler(void *hwdev, void *pri_handle, u16 vf_id, - u16 cmd, void *buf_in, u16 in_size, void *buf_out, u16 *out_size); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg.c b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg.c deleted file mode 100644 index d241f6a7947d..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg.c +++ /dev/null @@ -1,1334 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/etherdevice.h> -#include <linux/if_vlan.h> -#include <linux/ethtool.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/netdevice.h> -#include <linux/module.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic.h" -#include "spnic_nic_cmd.h" -#include "sphw_common.h" - -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); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !attr) - return -EINVAL; - - memset(&cons_idx_attr, 0, sizeof(cons_idx_attr)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - cons_idx_attr.func_idx = sphw_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_NIC_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) { - sdk_err(nic_cfg->dev_hdl, - "Failed to set ci attribute table, err: %d, status: 0x%x, out_size: 0x%x\n", - 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 && status != SPNIC_PF_SET_VF_ALREADY) - return -EINVAL; - - return 0; -} - -#define SPNIC_VLAN_ID_MASK 0x7FFF - -int spnic_set_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id, u16 channel) -{ - struct spnic_port_mac_set mac_info; - u16 out_size = sizeof(mac_info); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !mac_addr) - return -EINVAL; - - memset(&mac_info, 0, sizeof(mac_info)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if ((vlan_id & SPNIC_VLAN_ID_MASK) >= VLAN_N_VID) { - nic_err(nic_cfg->dev_hdl, "Invalid VLAN number: %d\n", - vlan_id & SPNIC_VLAN_ID_MASK); - return -EINVAL; - } - - mac_info.func_id = func_id; - mac_info.vlan_id = vlan_id; - ether_addr_copy(mac_info.mac, mac_addr); - - err = l2nic_msg_to_mgmt_sync_ch(hwdev, SPNIC_NIC_CMD_SET_MAC, - &mac_info, sizeof(mac_info), - &mac_info, &out_size, channel); - if (err || !out_size || spnic_check_mac_info(mac_info.msg_head.status, mac_info.vlan_id)) { - nic_err(nic_cfg->dev_hdl, - "Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, mac_info.msg_head.status, out_size, channel); - return -EINVAL; - } - - if (mac_info.msg_head.status == SPNIC_PF_SET_VF_ALREADY) { - nic_warn(nic_cfg->dev_hdl, "PF has already set VF mac, Ignore set operation\n"); - return SPNIC_PF_SET_VF_ALREADY; - } - - if (mac_info.msg_head.status == SPNIC_MGMT_STATUS_EXIST) { - nic_warn(nic_cfg->dev_hdl, "MAC is repeated. Ignore update operation\n"); - return 0; - } - - return 0; -} - -int spnic_del_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id, u16 channel) -{ - struct spnic_port_mac_set mac_info; - u16 out_size = sizeof(mac_info); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !mac_addr) - return -EINVAL; - - memset(&mac_info, 0, sizeof(mac_info)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if ((vlan_id & SPNIC_VLAN_ID_MASK) >= VLAN_N_VID) { - nic_err(nic_cfg->dev_hdl, "Invalid VLAN number: %d\n", - (vlan_id & SPNIC_VLAN_ID_MASK)); - return -EINVAL; - } - - mac_info.func_id = func_id; - mac_info.vlan_id = vlan_id; - ether_addr_copy(mac_info.mac, mac_addr); - - err = l2nic_msg_to_mgmt_sync_ch(hwdev, SPNIC_NIC_CMD_DEL_MAC, - &mac_info, sizeof(mac_info), &mac_info, - &out_size, channel); - if (err || !out_size || - (mac_info.msg_head.status && mac_info.msg_head.status != - SPNIC_PF_SET_VF_ALREADY)) { - nic_err(nic_cfg->dev_hdl, - "Failed to delete MAC, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, mac_info.msg_head.status, out_size, channel); - return -EINVAL; - } - - if (mac_info.msg_head.status == SPNIC_PF_SET_VF_ALREADY) { - nic_warn(nic_cfg->dev_hdl, "PF has already set VF mac, Ignore delete operation.\n"); - 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); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !old_mac || !new_mac) - return -EINVAL; - - memset(&mac_info, 0, sizeof(mac_info)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if ((vlan_id & SPNIC_VLAN_ID_MASK) >= VLAN_N_VID) { - nic_err(nic_cfg->dev_hdl, "Invalid VLAN number: %d\n", - vlan_id & SPNIC_VLAN_ID_MASK); - return -EINVAL; - } - - mac_info.func_id = func_id; - mac_info.vlan_id = vlan_id; - ether_addr_copy(mac_info.old_mac, old_mac); - ether_addr_copy(mac_info.new_mac, new_mac); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_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)) { - nic_err(nic_cfg->dev_hdl, - "Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x\n", - err, mac_info.msg_head.status, out_size); - return -EINVAL; - } - - if (mac_info.msg_head.status == SPNIC_PF_SET_VF_ALREADY) { - nic_warn(nic_cfg->dev_hdl, "PF has already set VF MAC. Ignore update operation\n"); - return SPNIC_PF_SET_VF_ALREADY; - } - - if (mac_info.msg_head.status == SPNIC_MGMT_STATUS_EXIST) { - nic_warn(nic_cfg->dev_hdl, "MAC is repeated. Ignore update operation\n"); - return 0; - } - - return 0; -} - -int spnic_get_default_mac(void *hwdev, u8 *mac_addr) -{ - struct spnic_port_mac_set mac_info; - u16 out_size = sizeof(mac_info); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !mac_addr) - return -EINVAL; - - memset(&mac_info, 0, sizeof(mac_info)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - mac_info.func_id = sphw_global_func_id(hwdev); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_GET_MAC, &mac_info, sizeof(mac_info), - &mac_info, &out_size); - if (err || !out_size || mac_info.msg_head.status) { - nic_err(nic_cfg->dev_hdl, - "Failed to get mac, err: %d, status: 0x%x, out size: 0x%x\n", - err, mac_info.msg_head.status, out_size); - return -EINVAL; - } - - ether_addr_copy(mac_addr, mac_info.mac); - - return 0; -} - -static int spnic_config_vlan(struct spnic_nic_cfg *nic_cfg, u8 opcode, u16 vlan_id, u16 func_id) -{ - struct spnic_cmd_vlan_config vlan_info; - u16 out_size = sizeof(vlan_info); - int err; - - memset(&vlan_info, 0, sizeof(vlan_info)); - vlan_info.opcode = opcode; - vlan_info.func_id = func_id; - vlan_info.vlan_id = vlan_id; - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_CFG_FUNC_VLAN, - &vlan_info, sizeof(vlan_info), - &vlan_info, &out_size); - if (err || !out_size || vlan_info.msg_head.status) { - nic_err(nic_cfg->dev_hdl, - "Failed to %s vlan, err: %d, status: 0x%x, out size: 0x%x\n", - opcode == SPNIC_CMD_OP_ADD ? "add" : "delete", - err, vlan_info.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} - -int spnic_add_vlan(void *hwdev, u16 vlan_id, u16 func_id) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - return spnic_config_vlan(nic_cfg, SPNIC_CMD_OP_ADD, vlan_id, func_id); -} - -int spnic_del_vlan(void *hwdev, u16 vlan_id, u16 func_id) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - return spnic_config_vlan(nic_cfg, SPNIC_CMD_OP_DEL, vlan_id, func_id); -} - -int spnic_set_vport_enable(void *hwdev, u16 func_id, bool enable, u16 channel) -{ - struct spnic_vport_state en_state; - u16 out_size = sizeof(en_state); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - memset(&en_state, 0, sizeof(en_state)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - en_state.func_id = func_id; - en_state.state = enable ? 1 : 0; - - err = l2nic_msg_to_mgmt_sync_ch(hwdev, SPNIC_NIC_CMD_SET_VPORT_ENABLE, - &en_state, sizeof(en_state), - &en_state, &out_size, channel); - if (err || !out_size || en_state.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set vport state, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n", - err, en_state.msg_head.status, out_size, channel); - return -EINVAL; - } - - return 0; -} - -int spnic_set_dcb_state(void *hwdev, struct spnic_dcb_state *dcb_state) -{ - struct vf_data_storage *vf_infos = NULL; - struct spnic_cmd_vf_dcb_state vf_dcb; - struct spnic_nic_cfg *nic_cfg = NULL; - u16 vf_id, out_size = 0; - int err; - - if (!hwdev || !dcb_state) - return -EINVAL; - - memset(&vf_dcb, 0, sizeof(vf_dcb)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if (!memcmp(&nic_cfg->dcb_state, dcb_state, sizeof(nic_cfg->dcb_state))) - return 0; - - memcpy(&vf_dcb.state, dcb_state, sizeof(vf_dcb.state)); - /* save in sdk, vf will get dcb state when probing */ - spnic_save_dcb_state(nic_cfg, dcb_state); - - /* notify statefull in pf, than notify all vf */ - spnic_notify_dcb_state_event(nic_cfg, dcb_state); - - /* not vf supported, don't need to notify vf */ - if (!nic_cfg->vf_infos) - return 0; - - vf_infos = nic_cfg->vf_infos; - for (vf_id = 0; vf_id < nic_cfg->max_vfs; vf_id++) { - if (vf_infos[vf_id].registered) { - vf_dcb.msg_head.status = 0; - out_size = sizeof(vf_dcb); - err = sphw_mbox_to_vf(hwdev, OS_VF_ID_TO_HW(vf_id), SPHW_MOD_L2NIC, - SPNIC_NIC_CMD_VF_COS, &vf_dcb, sizeof(vf_dcb), - &vf_dcb, &out_size, 0, SPHW_CHANNEL_NIC); - if (MSG_TO_MGMT_SYNC_RETURN_ERR(err, vf_dcb.msg_head.status, out_size)) - nic_err(nic_cfg->dev_hdl, - "Failed to notify dcb state to VF %u, err: %d, status: 0x%x, out size: 0x%x\n", - vf_id, err, vf_dcb.msg_head.status, out_size); - } - } - - return 0; -} - -int spnic_get_dcb_state(void *hwdev, struct spnic_dcb_state *dcb_state) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev || !dcb_state) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memcpy(dcb_state, &nic_cfg->dcb_state, sizeof(*dcb_state)); - - return 0; -} - -int spnic_save_dcb_state(struct spnic_nic_cfg *nic_cfg, struct spnic_dcb_state *dcb_state) -{ - memcpy(&nic_cfg->dcb_state, dcb_state, sizeof(*dcb_state)); - - return 0; -} - -int spnic_get_pf_dcb_state(void *hwdev, struct spnic_dcb_state *dcb_state) -{ - struct spnic_cmd_vf_dcb_state vf_dcb; - struct spnic_nic_cfg *nic_cfg = NULL; - u16 out_size = sizeof(vf_dcb); - int err; - - if (!hwdev || !dcb_state) - return -EINVAL; - - memset(&vf_dcb, 0, sizeof(vf_dcb)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if (sphw_func_type(hwdev) != TYPE_VF) { - nic_err(nic_cfg->dev_hdl, "Only vf need to get pf dcb state\n"); - return -EINVAL; - } - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_VF_COS, &vf_dcb, - sizeof(vf_dcb), &vf_dcb, &out_size); - if (err || !out_size || vf_dcb.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to get vf default cos, err: %d, status: 0x%x, out size: 0x%x\n", - err, vf_dcb.msg_head.status, out_size); - return -EFAULT; - } - - memcpy(dcb_state, &vf_dcb.state, sizeof(*dcb_state)); - /* Save dcb_state in hw for statefull module */ - spnic_save_dcb_state(nic_cfg, dcb_state); - - return 0; -} - -static int spnic_cfg_hw_pause(struct spnic_nic_cfg *nic_cfg, u8 opcode, - struct nic_pause_config *nic_pause) -{ - struct spnic_cmd_pause_config pause_info; - u16 out_size = sizeof(pause_info); - int err; - - memset(&pause_info, 0, sizeof(pause_info)); - - pause_info.port_id = sphw_physical_port_id(nic_cfg->hwdev); - pause_info.opcode = opcode; - if (opcode == SPNIC_CMD_OP_SET) { - pause_info.auto_neg = nic_pause->auto_neg; - pause_info.rx_pause = nic_pause->rx_pause; - pause_info.tx_pause = nic_pause->tx_pause; - } - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_CFG_PAUSE_INFO, - &pause_info, sizeof(pause_info), - &pause_info, &out_size); - if (err || !out_size || pause_info.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to %s pause info, err: %d, status: 0x%x, out size: 0x%x\n", - opcode == SPNIC_CMD_OP_SET ? "set" : "get", - err, pause_info.msg_head.status, out_size); - return -EINVAL; - } - - if (opcode == SPNIC_CMD_OP_GET) { - nic_pause->auto_neg = pause_info.auto_neg; - nic_pause->rx_pause = pause_info.rx_pause; - nic_pause->tx_pause = pause_info.tx_pause; - } - - return 0; -} - -int spnic_set_pause_info(void *hwdev, struct nic_pause_config nic_pause) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - down(&nic_cfg->cfg_lock); - - err = spnic_cfg_hw_pause(nic_cfg, SPNIC_CMD_OP_SET, &nic_pause); - if (err) { - up(&nic_cfg->cfg_lock); - return err; - } - - nic_cfg->pfc_en = 0; - nic_cfg->pfc_bitmap = 0; - nic_cfg->pause_set = true; - nic_cfg->nic_pause.auto_neg = nic_pause.auto_neg; - nic_cfg->nic_pause.rx_pause = nic_pause.rx_pause; - nic_cfg->nic_pause.tx_pause = nic_pause.tx_pause; - - up(&nic_cfg->cfg_lock); - - return 0; -} - -int spnic_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - int err = 0; - - if (!hwdev || !nic_pause) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - err = spnic_cfg_hw_pause(nic_cfg, SPNIC_CMD_OP_GET, nic_pause); - if (err) - return err; - - if (nic_cfg->pause_set || !nic_pause->auto_neg) { - nic_pause->rx_pause = nic_cfg->nic_pause.rx_pause; - nic_pause->tx_pause = nic_cfg->nic_pause.tx_pause; - } - - return 0; -} - -static int spnic_dcb_set_hw_pfc(struct spnic_nic_cfg *nic_cfg, u8 pfc_en, u8 pfc_bitmap) -{ - struct spnic_cmd_set_pfc pfc; - u16 out_size = sizeof(pfc); - int err; - - memset(&pfc, 0, sizeof(pfc)); - - pfc.port_id = sphw_physical_port_id(nic_cfg->hwdev); - pfc.pfc_bitmap = pfc_bitmap; - pfc.pfc_en = pfc_en; - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_SET_PFC, - &pfc, sizeof(pfc), &pfc, &out_size); - if (err || pfc.msg_head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, "Failed to set pfc, err: %d, status: 0x%x, out size: 0x%x\n", - err, pfc.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} - -int spnic_dcb_set_pfc(void *hwdev, u8 pfc_en, u8 pfc_bitmap) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - down(&nic_cfg->cfg_lock); - - err = spnic_dcb_set_hw_pfc(nic_cfg, pfc_en, pfc_bitmap); - if (err) { - up(&nic_cfg->cfg_lock); - return err; - } - - nic_cfg->pfc_en = pfc_en; - nic_cfg->pfc_bitmap = pfc_bitmap; - - /* pause settings is opposite from pfc */ - nic_cfg->nic_pause.rx_pause = pfc_en ? 0 : 1; - nic_cfg->nic_pause.tx_pause = pfc_en ? 0 : 1; - - up(&nic_cfg->cfg_lock); - - return 0; -} - -int spnic_dcb_set_ets(void *hwdev, u8 *cos_tc, u8 *cos_bw, u8 *cos_prio, - u8 *tc_bw, u8 *tc_prio) -{ - struct spnic_up_ets_cfg ets; - struct spnic_nic_cfg *nic_cfg = NULL; - u16 out_size = sizeof(ets); - u16 cos_bw_t = 0; - u8 tc_bw_t = 0; - int i, err; - - memset(&ets, 0, sizeof(ets)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - for (i = 0; i < SPNIC_DCB_COS_MAX; i++) { - cos_bw_t += *(cos_bw + i); - tc_bw_t += *(tc_bw + i); - - if (*(cos_tc + i) > SPNIC_DCB_TC_MAX) { - nic_err(nic_cfg->dev_hdl, "Invalid cos %d mapping tc: %u\n", - i, *(cos_tc + i)); - return -EINVAL; - } - } - - /* The sum of all TCs must be 100%, and the same for cos */ - if ((tc_bw_t != 100 && tc_bw_t != 0) || (cos_bw_t % 100) != 0) { - nic_err(nic_cfg->dev_hdl, - "Invalid pg_bw: %u or up_bw: %u\n", tc_bw_t, cos_bw_t); - return -EINVAL; - } - - ets.port_id = sphw_physical_port_id(hwdev); - memcpy(ets.cos_tc, cos_tc, SPNIC_DCB_COS_MAX); - memcpy(ets.cos_bw, cos_bw, SPNIC_DCB_COS_MAX); - memcpy(ets.cos_prio, cos_prio, SPNIC_DCB_COS_MAX); - memcpy(ets.tc_bw, tc_bw, SPNIC_DCB_TC_MAX); - memcpy(ets.tc_prio, tc_prio, SPNIC_DCB_TC_MAX); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_SET_ETS, - &ets, sizeof(ets), &ets, &out_size); - if (err || ets.msg_head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, - "Failed to set ets, err: %d, status: 0x%x, out size: 0x%x\n", - err, ets.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} - -int spnic_dcb_set_cos_up_map(void *hwdev, u8 cos_valid_bitmap, u8 *cos_up, u8 max_cos_num) -{ - struct spnic_cos_up_map map; - struct spnic_nic_cfg *nic_cfg = NULL; - u16 out_size = sizeof(map); - int err; - - if (!hwdev || !cos_up) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&map, 0, sizeof(map)); - - map.port_id = sphw_physical_port_id(hwdev); - map.cos_valid_mask = cos_valid_bitmap; - memcpy(map.map, cos_up, sizeof(map.map)); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_SETUP_COS_MAPPING, - &map, sizeof(map), &map, &out_size); - if (err || map.msg_head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, - "Failed to set cos2up map, err: %d, status: 0x%x, out size: 0x%x\n", - err, map.msg_head.status, out_size); - return -EFAULT; - } - - return 0; -} - -int spnic_flush_qps_res(void *hwdev) -{ - struct spnic_cmd_clear_qp_resource sq_res; - u16 out_size = sizeof(sq_res); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&sq_res, 0, sizeof(sq_res)); - - sq_res.func_id = sphw_global_func_id(hwdev); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_CLEAR_QP_RESOURCE, - &sq_res, sizeof(sq_res), &sq_res, - &out_size); - if (err || !out_size || sq_res.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to clear sq resources, err: %d, status: 0x%x, out size: 0x%x\n", - err, sq_res.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} - -int spnic_get_vport_stats(void *hwdev, struct spnic_vport_stats *stats) -{ - struct spnic_port_stats_info stats_info; - struct spnic_cmd_vport_stats vport_stats; - u16 out_size = sizeof(vport_stats); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !stats) - return -EINVAL; - - memset(&stats_info, 0, sizeof(stats_info)); - memset(&vport_stats, 0, sizeof(vport_stats)); - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - stats_info.func_id = sphw_global_func_id(hwdev); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_GET_VPORT_STAT, - &stats_info, sizeof(stats_info), - &vport_stats, &out_size); - if (err || !out_size || vport_stats.msg_head.status) { - nic_err(nic_cfg->dev_hdl, - "Failed to get function statistics, err: %d, status: 0x%x, out size: 0x%x\n", - err, vport_stats.msg_head.status, out_size); - return -EFAULT; - } - - memcpy(stats, &vport_stats.stats, sizeof(*stats)); - - return 0; -} - -int spnic_set_function_table(struct spnic_nic_cfg *nic_cfg, 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 = sphw_global_func_id(nic_cfg->hwdev); - cmd_func_tbl.cfg_bitmap = cfg_bitmap; - cmd_func_tbl.tbl_cfg = *cfg; - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_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) { - nic_err(nic_cfg->dev_hdl, - "Failed to set func table, 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(struct spnic_nic_cfg *nic_cfg) -{ - struct spnic_func_tbl_cfg func_tbl_cfg = {0}; - u32 cfg_bitmap = BIT(FUNC_CFG_INIT) | BIT(FUNC_CFG_MTU) | - BIT(FUNC_CFG_RX_BUF_SIZE); - - func_tbl_cfg.mtu = 0x3FFF; /* default, max mtu */ - func_tbl_cfg.rx_wqe_buf_size = nic_cfg->rx_buff_len; - - return spnic_set_function_table(nic_cfg, cfg_bitmap, &func_tbl_cfg); -} - -int spnic_set_port_mtu(void *hwdev, u16 new_mtu) -{ - struct spnic_func_tbl_cfg func_tbl_cfg = {0}; - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if (new_mtu < SPNIC_MIN_MTU_SIZE) { - nic_err(nic_cfg->dev_hdl, "Invalid mtu size: %ubytes, mtu size < %ubytes", - new_mtu, SPNIC_MIN_MTU_SIZE); - return -EINVAL; - } - - if (new_mtu > SPNIC_MAX_JUMBO_FRAME_SIZE) { - nic_err(nic_cfg->dev_hdl, "Invalid mtu size: %ubytes, mtu size > %ubytes", - new_mtu, SPNIC_MAX_JUMBO_FRAME_SIZE); - return -EINVAL; - } - - func_tbl_cfg.mtu = new_mtu; - return spnic_set_function_table(nic_cfg, BIT(FUNC_CFG_MTU), &func_tbl_cfg); -} - -static int nic_feature_nego(void *hwdev, u8 opcode, u64 *s_feature, u16 size) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_cmd_feature_nego feature_nego; - u16 out_size = sizeof(feature_nego); - int err; - - if (!hwdev || !s_feature || size > NIC_MAX_FEATURE_QWORD) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&feature_nego, 0, sizeof(feature_nego)); - feature_nego.func_id = sphw_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_NIC_CMD_FEATURE_NEGO, - &feature_nego, sizeof(feature_nego), - &feature_nego, &out_size); - if (err || !out_size || feature_nego.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to negotiate nic feature, err:%d, status: 0x%x, out_size: 0x%x\n", - err, feature_nego.msg_head.status, out_size); - return -EIO; - } - - if (opcode == SPNIC_CMD_OP_GET) - memcpy(s_feature, feature_nego.s_feature, size * sizeof(u64)); - - return 0; -} - -static int spnic_get_nic_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_nic_feature_to_hw(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - return nic_feature_nego(hwdev, SPNIC_CMD_OP_SET, &nic_cfg->feature_cap, 1); -} - -u64 spnic_get_feature_cap(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - return nic_cfg->feature_cap; -} - -void spnic_update_nic_feature(void *hwdev, u64 feature) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - nic_cfg->feature_cap = feature; - - nic_info(nic_cfg->dev_hdl, "Update nic feature to 0x%llx\n", nic_cfg->feature_cap); -} - -static inline int init_nic_hwdev_param_valid(void *hwdev, void *pcidev_hdl, void *dev_hdl) -{ - if (!hwdev || !pcidev_hdl || !dev_hdl) - return -EINVAL; - - return 0; -} - -/* spnic_init_nic_hwdev - init nic hwdev - * @hwdev: pointer to hwdev - * @pcidev_hdl: pointer to pcidev or handler - * @dev_hdl: pointer to pcidev->dev or handler, for sdk_err() or dma_alloc() - * @rx_buff_len: rx_buff_len is receive buffer length - */ -int spnic_init_nic_hwdev(void *hwdev, void *pcidev_hdl, void *dev_hdl, u16 rx_buff_len) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (init_nic_hwdev_param_valid(hwdev, pcidev_hdl, dev_hdl)) - return -EINVAL; - - nic_cfg = kzalloc(sizeof(*nic_cfg), GFP_KERNEL); - if (!nic_cfg) - return -ENOMEM; - - nic_cfg->dev_hdl = dev_hdl; - nic_cfg->pcidev_hdl = pcidev_hdl; - nic_cfg->hwdev = hwdev; - - sema_init(&nic_cfg->cfg_lock, 1); - mutex_init(&nic_cfg->sfp_mutex); - - err = sphw_register_service_adapter(hwdev, nic_cfg, SERVICE_T_NIC); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to register service adapter\n"); - goto register_sa_err; - } - - err = spnic_init_function_table(nic_cfg); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to init function table\n"); - goto init_func_tbl_err; - } - - err = spnic_get_nic_feature_from_hw(hwdev, &nic_cfg->feature_cap, 1); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to get nic features\n"); - goto get_feature_err; - } - - sdk_info(dev_hdl, "nic features: 0x%llx\n", nic_cfg->feature_cap); - - err = sphw_aeq_register_swe_cb(hwdev, SPHW_STATELESS_EVENT, spnic_nic_sw_aeqe_handler); - if (err) { - nic_err(nic_cfg->dev_hdl, - "Failed to register sw aeqe handler\n"); - goto register_sw_aeqe_err; - } - - err = spnic_vf_func_init(nic_cfg); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to init vf info\n"); - goto vf_init_err; - } - - nic_cfg->rx_buff_len = rx_buff_len; - - return 0; - -vf_init_err: - sphw_aeq_unregister_swe_cb(hwdev, SPHW_STATELESS_EVENT); - -register_sw_aeqe_err: -get_feature_err: -init_func_tbl_err: - sphw_unregister_service_adapter(hwdev, SERVICE_T_NIC); - -register_sa_err: - kfree(nic_cfg); - - return err; -} - -void spnic_free_nic_hwdev(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) - return; - - spnic_vf_func_free(nic_cfg); - - sphw_aeq_unregister_swe_cb(hwdev, SPHW_STATELESS_EVENT); - - sphw_unregister_service_adapter(hwdev, SERVICE_T_NIC); - - kfree(nic_cfg); -} - -/* to do : send cmd to MPU to drop nic tx pkt*/ -int spnic_force_drop_tx_pkt(void *hwdev) -{ - return 0; -} - -int spnic_set_rx_mode(void *hwdev, u32 enable) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_rx_mode_config rx_mode_cfg; - u16 out_size = sizeof(rx_mode_cfg); - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&rx_mode_cfg, 0, sizeof(rx_mode_cfg)); - rx_mode_cfg.func_id = sphw_global_func_id(hwdev); - rx_mode_cfg.rx_mode = enable; - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_SET_RX_MODE, - &rx_mode_cfg, sizeof(rx_mode_cfg), - &rx_mode_cfg, &out_size); - if (err || !out_size || rx_mode_cfg.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set rx mode, err: %d, status: 0x%x, out size: 0x%x\n", - err, rx_mode_cfg.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} - -int spnic_set_rx_vlan_offload(void *hwdev, u8 en) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_cmd_vlan_offload vlan_cfg; - u16 out_size = sizeof(vlan_cfg); - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&vlan_cfg, 0, sizeof(vlan_cfg)); - vlan_cfg.func_id = sphw_global_func_id(hwdev); - vlan_cfg.vlan_offload = en; - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_SET_RX_VLAN_OFFLOAD, - &vlan_cfg, sizeof(vlan_cfg), - &vlan_cfg, &out_size); - if (err || !out_size || vlan_cfg.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set rx vlan offload, err: %d, status: 0x%x, out size: 0x%x\n", - err, vlan_cfg.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} - -int spnic_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id) -{ - struct vf_data_storage *vf_info = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - u16 func_id; - int err; - - if (!hwdev || old_vlan >= VLAN_N_VID || new_vlan >= VLAN_N_VID) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - vf_info = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf_id); - - if (!nic_cfg->vf_infos || is_zero_ether_addr(vf_info->drv_mac_addr)) - return 0; - - func_id = sphw_glb_pf_vf_offset(nic_cfg->hwdev) + (u16)vf_id; - - err = spnic_del_mac(nic_cfg->hwdev, vf_info->drv_mac_addr, - old_vlan, func_id, SPHW_CHANNEL_NIC); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to delete VF %d MAC %pM vlan %u\n", - HW_VF_ID_TO_OS(vf_id), vf_info->drv_mac_addr, old_vlan); - return err; - } - - err = spnic_set_mac(nic_cfg->hwdev, vf_info->drv_mac_addr, - new_vlan, func_id, SPHW_CHANNEL_NIC); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to add VF %d MAC %pM vlan %u\n", - HW_VF_ID_TO_OS(vf_id), vf_info->drv_mac_addr, new_vlan); - spnic_set_mac(nic_cfg->hwdev, vf_info->drv_mac_addr, - old_vlan, func_id, SPHW_CHANNEL_NIC); - return err; - } - - return 0; -} - -static int spnic_set_rx_lro(void *hwdev, u8 ipv4_en, u8 ipv6_en, u8 lro_max_pkt_len) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_cmd_lro_config lro_cfg; - u16 out_size = sizeof(lro_cfg); - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&lro_cfg, 0, sizeof(lro_cfg)); - lro_cfg.func_id = sphw_global_func_id(hwdev); - lro_cfg.opcode = SPNIC_CMD_OP_SET; - lro_cfg.lro_ipv4_en = ipv4_en; - lro_cfg.lro_ipv6_en = ipv6_en; - lro_cfg.lro_max_pkt_len = lro_max_pkt_len; - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_CFG_RX_LRO, - &lro_cfg, sizeof(lro_cfg), - &lro_cfg, &out_size); - if (err || !out_size || lro_cfg.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set lro offload, err: %d, status: 0x%x, out size: 0x%x\n", - err, lro_cfg.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} - -static int spnic_set_rx_lro_timer(void *hwdev, u32 timer_value) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_cmd_lro_timer lro_timer; - u16 out_size = sizeof(lro_timer); - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&lro_timer, 0, sizeof(lro_timer)); - lro_timer.opcode = SPNIC_CMD_OP_SET; - lro_timer.timer = timer_value; - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_CFG_LRO_TIMER, - &lro_timer, sizeof(lro_timer), - &lro_timer, &out_size); - if (err || !out_size || lro_timer.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set lro timer, err: %d, status: 0x%x, out size: 0x%x\n", - err, lro_timer.msg_head.status, out_size); - - return -EINVAL; - } - - return 0; -} - -int spnic_set_rx_lro_state(void *hwdev, u8 lro_en, u32 lro_timer, u32 lro_max_pkt_len) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - u8 ipv4_en = 0, ipv6_en = 0; - int err; - - if (!hwdev) - return -EINVAL; - - ipv4_en = lro_en ? 1 : 0; - ipv6_en = lro_en ? 1 : 0; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - nic_info(nic_cfg->dev_hdl, "Set LRO max coalesce packet size to %uK\n", - lro_max_pkt_len); - - err = spnic_set_rx_lro(hwdev, ipv4_en, ipv6_en, (u8)lro_max_pkt_len); - if (err) - return err; - - /* we don't set LRO timer for VF */ - if (sphw_func_type(hwdev) == TYPE_VF) - return 0; - - nic_info(nic_cfg->dev_hdl, "Set LRO timer to %u\n", lro_timer); - - return spnic_set_rx_lro_timer(hwdev, lro_timer); -} - -int spnic_set_vlan_fliter(void *hwdev, u32 vlan_filter_ctrl) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_cmd_set_vlan_filter vlan_filter; - u16 out_size = sizeof(vlan_filter); - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&vlan_filter, 0, sizeof(vlan_filter)); - vlan_filter.func_id = sphw_global_func_id(hwdev); - vlan_filter.vlan_filter_ctrl = vlan_filter_ctrl; - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_SET_VLAN_FILTER_EN, - &vlan_filter, sizeof(vlan_filter), - &vlan_filter, &out_size); - if (err || !out_size || vlan_filter.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set vlan filter, err: %d, status: 0x%x, out size: 0x%x\n", - err, vlan_filter.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} - -int spnic_add_tcam_rule(void *hwdev, struct nic_tcam_cfg_rule *tcam_rule) -{ - u16 out_size = sizeof(struct nic_cmd_fdir_add_rule); - struct nic_cmd_fdir_add_rule tcam_cmd; - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !tcam_rule) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (tcam_rule->index >= SPNIC_MAX_TCAM_RULES_NUM) { - nic_err(nic_cfg->dev_hdl, "Tcam rules num to add is invalid\n"); - return -EINVAL; - } - - memset(&tcam_cmd, 0, sizeof(struct nic_cmd_fdir_add_rule)); - memcpy((void *)&tcam_cmd.rule, (void *)tcam_rule, - sizeof(struct nic_tcam_cfg_rule)); - tcam_cmd.func_id = sphw_global_func_id(hwdev); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_ADD_TC_FLOW, - &tcam_cmd, sizeof(tcam_cmd), - &tcam_cmd, &out_size); - if (err || tcam_cmd.head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, - "Add tcam rule failed, err: %d, status: 0x%x, out size: 0x%x\n", - err, tcam_cmd.head.status, out_size); - return -EIO; - } - - return 0; -} - -int spnic_del_tcam_rule(void *hwdev, u32 index) -{ - u16 out_size = sizeof(struct nic_cmd_fdir_del_rules); - struct nic_cmd_fdir_del_rules tcam_cmd; - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (index >= SPNIC_MAX_TCAM_RULES_NUM) { - nic_err(nic_cfg->dev_hdl, "Tcam rules num to del is invalid\n"); - return -EINVAL; - } - - memset(&tcam_cmd, 0, sizeof(struct nic_cmd_fdir_del_rules)); - tcam_cmd.index_start = index; - tcam_cmd.index_num = 1; - tcam_cmd.func_id = sphw_global_func_id(hwdev); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_DEL_TC_FLOW, - &tcam_cmd, sizeof(tcam_cmd), - &tcam_cmd, &out_size); - if (err || tcam_cmd.head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, "Del tcam rule failed, err: %d, status: 0x%x, out size: 0x%x\n", - err, tcam_cmd.head.status, out_size); - return -EIO; - } - - return 0; -} - -/** - * spnic_mgmt_tcam_block - alloc or free tcam block for IO packet. - * - * @param hwdev - * The hardware interface of a nic device. - * @param alloc_en - * 1 alloc block. - * 0 free block. - * @param index - * block index from firmware. - * @return - * 0 on success, - * negative error value otherwise. - */ -static int spnic_mgmt_tcam_block(void *hwdev, u8 alloc_en, u16 *index) -{ - struct nic_cmd_ctrl_tcam_block_out tcam_block_info; - u16 out_size = sizeof(struct nic_cmd_ctrl_tcam_block_out); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !index) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&tcam_block_info, 0, sizeof(struct nic_cmd_ctrl_tcam_block_out)); - - tcam_block_info.func_id = sphw_global_func_id(hwdev); - tcam_block_info.alloc_en = alloc_en; - tcam_block_info.tcam_type = SPNIC_TCAM_BLOCK_NORMAL_TYPE; - tcam_block_info.tcam_block_index = *index; - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_CFG_TCAM_BLOCK, - &tcam_block_info, sizeof(tcam_block_info), - &tcam_block_info, &out_size); - if (err || tcam_block_info.head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, - "Set tcam block failed, err: %d, status: 0x%x, out size: 0x%x\n", - err, tcam_block_info.head.status, out_size); - return -EIO; - } - - if (alloc_en) - *index = tcam_block_info.tcam_block_index; - - return 0; -} - -int spnic_alloc_tcam_block(void *hwdev, u16 *index) -{ - return spnic_mgmt_tcam_block(hwdev, SPNIC_TCAM_BLOCK_ENABLE, index); -} - -int spnic_free_tcam_block(void *hwdev, u16 *index) -{ - return spnic_mgmt_tcam_block(hwdev, SPNIC_TCAM_BLOCK_DISABLE, index); -} - -int spnic_set_fdir_tcam_rule_filter(void *hwdev, bool enable) -{ - struct nic_cmd_set_tcam_enable port_tcam_cmd; - u16 out_size = sizeof(port_tcam_cmd); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&port_tcam_cmd, 0, sizeof(port_tcam_cmd)); - port_tcam_cmd.func_id = sphw_global_func_id(hwdev); - port_tcam_cmd.tcam_enable = (u8)enable; - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_ENABLE_TCAM, - &port_tcam_cmd, sizeof(port_tcam_cmd), - &port_tcam_cmd, &out_size); - if (err || port_tcam_cmd.head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, "Set fdir tcam filter failed, err: %d, status: 0x%x, out size: 0x%x, enable: 0x%x\n", - err, port_tcam_cmd.head.status, out_size, - enable); - return -EIO; - } - - return 0; -} - -int spnic_flush_tcam_rule(void *hwdev) -{ - struct nic_cmd_flush_tcam_rules tcam_flush; - u16 out_size = sizeof(struct nic_cmd_flush_tcam_rules); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&tcam_flush, 0, sizeof(struct nic_cmd_flush_tcam_rules)); - tcam_flush.func_id = sphw_global_func_id(hwdev); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_FLUSH_TCAM, - &tcam_flush, - sizeof(struct nic_cmd_flush_tcam_rules), - &tcam_flush, &out_size); - if (err || tcam_flush.head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, - "Flush tcam fdir rules failed, err: %d, status: 0x%x, out size: 0x%x\n", - err, tcam_flush.head.status, out_size); - return -EIO; - } - - return 0; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg.h b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg.h deleted file mode 100644 index f280b41fe362..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg.h +++ /dev/null @@ -1,709 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_NIC_CFG_H -#define SPNIC_NIC_CFG_H - -#include <linux/if_link.h> - -#include "spnic_nic_cmd.h" -#include "spnic_mgmt_interface.h" -#include "spnic_mag_cmd.h" - -#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_VLAN_PRIORITY_SHIFT 13 - -#define SPNIC_RSS_KEY_RSV_NUM 2 - -#define SPNIC_MIN_MTU_SIZE 256 -#define SPNIC_MAX_JUMBO_FRAME_SIZE 9600 - -#define SPNIC_PF_SET_VF_ALREADY 0x4 -#define SPNIC_MGMT_STATUS_EXIST 0x6 - -#define SPNIC_LOWEST_LATENCY 1 -#define SPNIC_MULTI_VM_LATENCY 32 -#define SPNIC_MULTI_VM_PENDING_LIMIT 4 -#define SPNIC_RX_RATE_LOW 400000 -#define SPNIC_RX_COAL_TIME_LOW 16 -#define SPNIC_RX_PENDING_LIMIT_LOW 2 -#define SPNIC_RX_RATE_HIGH 1000000 -#define SPNIC_RX_COAL_TIME_HIGH 225 -#define SPNIC_RX_PENDING_LIMIT_HIGH 8 -#define SPNIC_RX_RATE_THRESH 50000 -#define SPNIC_TX_RATE_THRESH 50000 -#define SPNIC_RX_RATE_LOW_VM 100000 -#define SPNIC_RX_PENDING_LIMIT_HIGH_VM 87 - -enum spnic_valid_link_settings { - HILINK_LINK_SET_SPEED = 0x1, - HILINK_LINK_SET_AUTONEG = 0x2, - HILINK_LINK_SET_FEC = 0x4, -}; - -struct spnic_link_ksettings { - u32 valid_bitmap; - u8 speed; /* enum nic_speed_level */ - u8 autoneg; /* 0 - off; 1 - on */ - u8 fec; /* 0 - RSFEC; 1 - BASEFEC; 2 - NOFEC */ -}; - -u64 spnic_get_feature_cap(void *hwdev); - -#define SPNIC_SUPPORT_FEATURE(hwdev, feature) (spnic_get_feature_cap(hwdev) & NIC_F_##feature) -#define SPNIC_SUPPORT_CSUM(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, CSUM) -#define SPNIC_SUPPORT_SCTP_CRC(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, SCTP_CRC) -#define SPNIC_SUPPORT_TSO(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, TSO) -#define SPNIC_SUPPORT_UFO(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, UFO) -#define SPNIC_SUPPORT_LRO(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, LRO) -#define SPNIC_SUPPORT_RSS(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, RSS) -#define SPNIC_SUPPORT_RXVLAN_FILTER(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, RX_VLAN_FILTER) -#define SPNIC_SUPPORT_VLAN_OFFLOAD(hwdev) (SPNIC_SUPPORT_FEATURE(hwdev, RX_VLAN_STRIP) && \ - SPNIC_SUPPORT_FEATURE(hwdev, TX_VLAN_INSERT)) -#define SPNIC_SUPPORT_VXLAN_OFFLOAD(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, VXLAN_OFFLOAD) -#define SPNIC_SUPPORT_IPSEC_OFFLOAD(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, IPSEC_OFFLOAD) -#define SPNIC_SUPPORT_FDIR(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, FDIR) -#define SPNIC_SUPPORT_PROMISC(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, PROMISC) -#define SPNIC_SUPPORT_ALLMULTI(hwdev) SPNIC_SUPPORT_FEATURE(hwdev, ALLMULTI) - -struct nic_rss_type { - u8 tcp_ipv6_ext; - u8 ipv6_ext; - u8 tcp_ipv6; - u8 ipv6; - u8 tcp_ipv4; - u8 ipv4; - u8 udp_ipv6; - u8 udp_ipv4; -}; - -enum spnic_rss_hash_type { - SPNIC_RSS_HASH_ENGINE_TYPE_XOR = 0, - SPNIC_RSS_HASH_ENGINE_TYPE_TOEP, - SPNIC_RSS_HASH_ENGINE_TYPE_MAX, -}; - -/* rss */ -struct nic_rss_indirect_tbl { - u32 rsvd[4]; /* Make sure that 16B beyond entry[] */ - u16 entry[SPNIC_RSS_INDIR_SIZE]; -}; - -struct nic_rss_context_tbl { - u32 rsvd[4]; - u32 ctx; -}; - -#define NIC_CONFIG_ALL_QUEUE_VLAN_CTX 0xFFFF -struct nic_vlan_ctx { - u32 func_id; - u32 qid; /* if qid = 0xFFFF, config current function all queue */ - u32 vlan_tag; - u32 vlan_mode; - u32 vlan_sel; -}; - -enum spnic_link_status { - SPNIC_LINK_DOWN = 0, - SPNIC_LINK_UP -}; - -struct nic_port_info { - u8 port_type; - u8 autoneg_cap; - u8 autoneg_state; - u8 duplex; - u8 speed; - u8 fec; - u32 supported_mode; - u32 advertised_mode; -}; - -struct nic_pause_config { - u8 auto_neg; - u8 rx_pause; - u8 tx_pause; -}; - -#define MODULE_TYPE_SFP 0x3 -#define MODULE_TYPE_QSFP28 0x11 -#define MODULE_TYPE_QSFP 0x0C -#define MODULE_TYPE_QSFP_PLUS 0x0D - -#define TCAM_IP_TYPE_MASK 0x1 -#define TCAM_TUNNEL_TYPE_MASK 0xF -#define TCAM_FUNC_ID_MASK 0x7FFF - -struct spnic_tcam_key_ipv4_mem { - u32 rsvd1:4; - u32 tunnel_type:4; - u32 ip_proto:8; - u32 rsvd0:16; - u32 sipv4_h:16; - u32 ip_type:1; - u32 function_id:15; - u32 dipv4_h:16; - u32 sipv4_l:16; - u32 rsvd2:16; - u32 dipv4_l:16; - u32 rsvd3; - u32 dport:16; - u32 rsvd4:16; - u32 rsvd5:16; - u32 sport:16; - u32 outer_sipv4_h:16; - u32 rsvd6:16; - u32 outer_dipv4_h:16; - u32 outer_sipv4_l:16; - u32 vni_h:16; - u32 outer_dipv4_l:16; - u32 rsvd7:16; - u32 vni_l:16; -}; - -struct spnic_tcam_key_ipv6_mem { - u32 rsvd1:4; - u32 tunnel_type:4; - u32 ip_proto:8; - u32 rsvd0:16; - u32 sipv6_key0:16; - u32 ip_type:1; - u32 function_id:15; - u32 sipv6_key2:16; - u32 sipv6_key1:16; - u32 sipv6_key4:16; - u32 sipv6_key3:16; - u32 sipv6_key6:16; - u32 sipv6_key5:16; - u32 dport:16; - u32 sipv6_key7:16; - u32 dipv6_key0:16; - u32 sport:16; - u32 dipv6_key2:16; - u32 dipv6_key1:16; - u32 dipv6_key4:16; - u32 dipv6_key3:16; - u32 dipv6_key6:16; - u32 dipv6_key5:16; - u32 rsvd2:16; - u32 dipv6_key7:16; -}; - -struct tag_tcam_key { - union { - struct spnic_tcam_key_ipv4_mem key_info; - struct spnic_tcam_key_ipv6_mem key_info_ipv6; - }; - - union { - struct spnic_tcam_key_ipv4_mem key_mask; - struct spnic_tcam_key_ipv6_mem key_mask_ipv6; - }; -}; - -int spnic_add_tcam_rule(void *hwdev, struct nic_tcam_cfg_rule *tcam_rule); -int spnic_del_tcam_rule(void *hwdev, u32 index); - -int spnic_alloc_tcam_block(void *hwdev, u16 *index); -int spnic_free_tcam_block(void *hwdev, u16 *index); - -int spnic_set_fdir_tcam_rule_filter(void *hwdev, bool enable); - -int spnic_flush_tcam_rule(void *hwdev); - -/* * - * @brief spnic_update_mac - update mac address to hardware - * @param hwdev: device pointer to hwdev - * @param old_mac: old mac to delete - * @param new_mac: new mac to update - * @param 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); - -/* * - * @brief spnic_get_default_mac - get default mac address - * @param hwdev: device pointer to hwdev - * @param mac_addr: mac address from hardware - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_get_default_mac(void *hwdev, u8 *mac_addr); - -/* * - * @brief spnic_set_port_mtu - set function mtu - * @param hwdev: device pointer to hwdev - * @param new_mtu: mtu - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_port_mtu(void *hwdev, u16 new_mtu); - -/* * - * @brief spnic_get_link_state - get link state - * @param hwdev: device pointer to hwdev - * @param 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); - -/* * - * @brief spnic_get_vport_stats - get function stats - * @param hwdev: device pointer to hwdev - * @param stats: function stats - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_get_vport_stats(void *hwdev, struct spnic_vport_stats *stats); - -/* * - * @brief spnic_notify_all_vfs_link_changed - notify to all vfs link changed - * @param hwdev: device pointer to hwdev - * @param link_status: link state, 0-link down, 1-link up - */ -void spnic_notify_all_vfs_link_changed(void *hwdev, u8 link_status); - -/* * - * @brief spnic_force_drop_tx_pkt - force drop tx packet - * @param hwdev: device pointer to hwdev - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_force_drop_tx_pkt(void *hwdev); - -/* * - * @brief spnic_set_rx_mode - set function rx mode - * @param hwdev: device pointer to hwdev - * @param enable: rx mode state - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_rx_mode(void *hwdev, u32 enable); - -/* * - * @brief spnic_set_rx_vlan_offload - set function vlan offload valid state - * @param hwdev: device pointer to hwdev - * @param en: 0-disable, 1-enable - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_rx_vlan_offload(void *hwdev, u8 en); - -/* * - * @brief spnic_set_rx_lro_state - set rx LRO configuration - * @param hwdev: device pointer to hwdev - * @param lro_en: 0-disable, 1-enable - * @param lro_timer: LRO aggregation timeout - * @param lro_max_pkt_len: LRO coalesce packet size(unit is 1K) - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_rx_lro_state(void *hwdev, u8 lro_en, u32 lro_timer, u32 lro_max_pkt_len); - -/* * - * @brief spnic_set_vf_spoofchk - set vf spoofchk - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @param spoofchk: spoofchk - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_vf_spoofchk(void *hwdev, u16 vf_id, bool spoofchk); - -/* * - * @brief spnic_vf_info_spoofchk - get vf spoofchk info - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @retval spoofchk state - */ -bool spnic_vf_info_spoofchk(void *hwdev, int vf_id); - -/* * - * @brief spnic_add_vf_vlan - add vf vlan id - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @param vlan: vlan id - * @param qos: qos - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_add_vf_vlan(void *hwdev, int vf_id, u16 vlan, u8 qos); - -/* * - * @brief spnic_kill_vf_vlan - kill vf vlan - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @param vlan: vlan id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_kill_vf_vlan(void *hwdev, int vf_id); - -/* * - * @brief spnic_set_vf_mac - set vf mac - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @param mac_addr: vf mac address - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_vf_mac(void *hwdev, int vf_id, unsigned char *mac_addr); - -/* * - * @brief spnic_vf_info_vlanprio - get vf vlan priority - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @retval zero: vlan priority - */ -u16 spnic_vf_info_vlanprio(void *hwdev, int vf_id); - -/* * - * @brief spnic_set_vf_tx_rate - set vf tx rate - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @param max_rate: max rate - * @param min_rate: min rate - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_vf_tx_rate(void *hwdev, u16 vf_id, u32 max_rate, u32 min_rate); - -/* * - * @brief spnic_set_vf_tx_rate - set vf tx rate - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @param ivi: vf info - * @retval zero: success - * @retval non-zero: failure - */ -void spnic_get_vf_config(void *hwdev, u16 vf_id, struct ifla_vf_info *ivi); - -/* * - * @brief spnic_set_vf_link_state - set vf link state - * @param hwdev: device pointer to hwdev - * @param vf_id: vf id - * @param link: link state - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_vf_link_state(void *hwdev, u16 vf_id, int link); - -/* * - * @brief spnic_get_port_info - set port info - * @param hwdev: device pointer to hwdev - * @param port_info: port info - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_get_port_info(void *hwdev, struct nic_port_info *port_info, u16 channel); - -/* * - * @brief spnic_set_rss_type - set rss type - * @param hwdev: device pointer to hwdev - * @param rss_type: rss type - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_rss_type(void *hwdev, struct nic_rss_type rss_type); - -/* * - * @brief spnic_get_rss_type - get rss type - * @param hwdev: device pointer to hwdev - * @param rss_type: rss type - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_get_rss_type(void *hwdev, struct nic_rss_type *rss_type); - -/* * - * @brief spnic_rss_get_hash_engine - get rss hash engine - * @param hwdev: device pointer to hwdev - * @param type: hash engine - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_rss_get_hash_engine(void *hwdev, u8 *type); - -/* * - * @brief spnic_rss_set_hash_engine - set rss hash engine - * @param hwdev: device pointer to hwdev - * @param type: hash engine - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_rss_set_hash_engine(void *hwdev, u8 type); - -/* * - * @brief spnic_rss_cfg - set rss configuration - * @param hwdev: device pointer to hwdev - * @param rss_en: enable rss flag - * @param type: number of TC - * @param prio_tc: priorityof TC - * @param num_qps: number of queue - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_rss_cfg(void *hwdev, u8 rss_en, u8 tc_num, u8 *prio_tc, u16 num_qps); - -/* * - * @brief spnic_rss_set_template_tbl - set template table - * @param hwdev: device pointer to hwdev - * @param key: rss key - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_rss_set_hash_key(void *hwdev, const u8 *key); - -/* * - * @brief spnic_rss_get_template_tbl - get template table - * @param hwdev: device pointer to hwdev - * @param key: rss key - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_rss_get_hash_key(void *hwdev, u8 *key); - -/* * - * @brief spnic_refresh_nic_cfg - refresh port cfg - * @param hwdev: device pointer to hwdev - * @param port_info: port information - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_refresh_nic_cfg(void *hwdev, struct nic_port_info *port_info); - -/* * - * @brief spnic_add_vlan - add vlan - * @param hwdev: device pointer to hwdev - * @param vlan_id: vlan id - * @param func_id: function id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_add_vlan(void *hwdev, u16 vlan_id, u16 func_id); - -/* * - * @brief spnic_del_vlan - delete vlan - * @param hwdev: device pointer to hwdev - * @param vlan_id: vlan id - * @param func_id: function id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_del_vlan(void *hwdev, u16 vlan_id, u16 func_id); - -/* * - * @brief spnic_set_mac - set mac address - * @param hwdev: device pointer to hwdev - * @param mac_addr: mac address from hardware - * @param vlan_id: vlan id - * @param func_id: function index - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id, u16 channel); - -/* * - * @brief spnic_del_mac - delete mac address - * @param hwdev: device pointer to hwdev - * @param mac_addr: mac address from hardware - * @param vlan_id: vlan id - * @param func_id: function index - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_del_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id, u16 channel); - -/* * - * @brief spnic_set_vport_enable - set function valid status - * @param hwdev: device pointer to hwdev - * @param func_id: global function index - * @param enable: 0-disable, 1-enable - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_vport_enable(void *hwdev, u16 func_id, bool enable, u16 channel); - -/* * - * @brief spnic_set_port_enable - set port status - * @param hwdev: device pointer to hwdev - * @param enable: 0-disable, 1-enable - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_set_port_enable(void *hwdev, bool enable, u16 channel); - -/* * - * @brief spnic_flush_qps_res - flush queue pairs resource in hardware - * @param hwdev: device pointer to hwdev - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_flush_qps_res(void *hwdev); - -/* * - * @brief spnic_init_nic_hwdev - init nic hwdev - * @param hwdev: device pointer to hwdev - * @param pcidev_hdl: pointer to pcidev or handler - * @param dev_hdl: pointer to pcidev->dev or handler, for sdk_err() or - * dma_alloc() - * @param rx_buff_len: rx_buff_len is receive buffer length - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_init_nic_hwdev(void *hwdev, void *pcidev_hdl, void *dev_hdl, u16 rx_buff_len); - -/* * - * @brief spnic_free_nic_hwdev - free nic hwdev - * @param hwdev: device pointer to hwdev - * @retval zero: success - * @retval non-zero: failure - */ -void spnic_free_nic_hwdev(void *hwdev); - -/* * - * @brief spnic_get_speed - set link speed - * @param hwdev: device pointer to hwdev - * @param port_info: link speed - * @param channel: channel id - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_get_speed(void *hwdev, enum mag_cmd_port_speed *speed, u16 channel); - -int spnic_get_dcb_state(void *hwdev, struct spnic_dcb_state *dcb_state); - -int spnic_get_pf_dcb_state(void *hwdev, struct spnic_dcb_state *dcb_state); - -/* * - * @brief spnic_create_qps - create queue pairs - * @param hwdev: device pointer to hwdev - * @param num_qp: number of queue pairs - * @param sq_depth: sq depth - * @param rq_depth: rq depth - * @param qps_msix_arry: msix info - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_create_qps(void *hwdev, u16 num_qp, u32 sq_depth, u32 rq_depth, - struct irq_info *qps_msix_arry); - -/* * - * @brief spnic_destroy_qps - destroy queue pairs - * @param hwdev: device pointer to hwdev - */ -void spnic_destroy_qps(void *hwdev); - -enum spnic_queue_type { - SPNIC_SQ, - SPNIC_RQ, - SPNIC_MAX_QUEUE_TYPE -}; - -/* * - * @brief spnic_get_nic_queue - get nic queue - * @param hwdev: device pointer to hwdev - * @param q_id: queue index - * @param q_type: queue type - * @retval queue address - */ -void *spnic_get_nic_queue(void *hwdev, u16 q_id, enum spnic_queue_type q_type); - -/* * - * @brief spnic_init_qp_ctxts - init queue pair context - * @param hwdev: device pointer to hwdev - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_init_qp_ctxts(void *hwdev); - -/* * - * @brief spnic_free_qp_ctxts - free queue pairs - * @param hwdev: device pointer to hwdev - */ -void spnic_free_qp_ctxts(void *hwdev); - -/* * - * @brief spnic_rss_set_indir_tbl - set rss indirect table - * @param hwdev: device pointer to hwdev - * @param indir_table: rss indirect table - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_rss_set_indir_tbl(void *hwdev, const u32 *indir_table); - -/* * - * @brief spnic_rss_get_indir_tbl - get rss indirect table - * @param hwdev: device pointer to hwdev - * @param indir_table: rss indirect table - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_rss_get_indir_tbl(void *hwdev, u32 *indir_table); - -/* * - * @brief spnic_get_phy_port_stats - get port stats - * @param hwdev: device pointer to hwdev - * @param stats: port stats - * @retval zero: success - * @retval non-zero: failure - */ -int spnic_get_phy_port_stats(void *hwdev, struct mag_cmd_port_stats *stats); - -int spnic_set_port_funcs_state(void *hwdev, bool enable); - -int spnic_reset_port_link_cfg(void *hwdev); - -int spnic_force_port_relink(void *hwdev); - -int spnic_set_dcb_state(void *hwdev, struct spnic_dcb_state *dcb_state); - -int spnic_dcb_set_pfc(void *hwdev, u8 pfc_en, u8 pfc_bitmap); - -int spnic_dcb_get_pfc(void *hwdev, u8 *pfc_en_bitmap); - -int spnic_dcb_set_ets(void *hwdev, u8 *cos_tc, u8 *cos_bw, u8 *cos_prio, u8 *tc_bw, u8 *tc_prio); - -int spnic_dcb_set_cos_up_map(void *hwdev, u8 cos_valid_bitmap, u8 *cos_up, u8 max_cos_num); - -int spnic_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause); - -int spnic_set_pause_info(void *hwdev, struct nic_pause_config nic_pause); - -int spnic_set_link_settings(void *hwdev, struct spnic_link_ksettings *settings); - -int spnic_set_vlan_fliter(void *hwdev, u32 vlan_filter_ctrl); - -void spnic_clear_vfs_info(void *hwdev); - -int spnic_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id); - -int spnic_set_led_status(void *hwdev, enum mag_led_type type, enum mag_led_mode mode); - -int spnic_set_func_capture_en(void *hwdev, u16 func_id, bool cap_en); - -int spnic_set_loopback_mode(void *hwdev, u8 mode, u8 enable); -int spnic_get_loopback_mode(void *hwdev, u8 *mode, u8 *enable); - -bool spnic_get_vf_trust(void *hwdev, int vf_id); -int spnic_set_vf_trust(void *hwdev, u16 vf_id, bool trust); - -int spnic_set_autoneg(void *hwdev, bool enable); - -int spnic_get_sfp_type(void *hwdev, u8 *sfp_type, u8 *sfp_type_ext); -int spnic_get_sfp_eeprom(void *hwdev, u8 *data, u32 len); - -int spnic_set_nic_feature_to_hw(void *hwdeve); -void spnic_update_nic_feature(void *hwdev, u64 feature); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg_vf.c b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg_vf.c deleted file mode 100644 index 634f82153dff..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cfg_vf.c +++ /dev/null @@ -1,658 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/etherdevice.h> -#include <linux/if_vlan.h> -#include <linux/ethtool.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/netdevice.h> -#include <linux/module.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic.h" -#include "spnic_nic_cmd.h" - -static unsigned char set_vf_link_state; -module_param(set_vf_link_state, byte, 0444); -MODULE_PARM_DESC(set_vf_link_state, "Set vf link state, 0 represents link auto, 1 represents link always up, 2 represents link always down. - default is 0."); - -/* In order to adapt different linux version */ -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 */ -}; - -#define NIC_CVLAN_INSERT_ENABLE 0x1 -#define NIC_QINQ_INSERT_ENABLE 0X3 -static int spnic_set_vlan_ctx(struct spnic_nic_cfg *nic_cfg, u16 func_id, - u16 vlan_tag, u16 q_id, bool add) -{ - struct nic_vlan_ctx *vlan_ctx = NULL; - struct sphw_cmd_buf *cmd_buf = NULL; - u64 out_param = 0; - int err; - - cmd_buf = sphw_alloc_cmd_buf(nic_cfg->hwdev); - if (!cmd_buf) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate cmd buf\n"); - return -ENOMEM; - } - - cmd_buf->size = sizeof(struct nic_vlan_ctx); - vlan_ctx = (struct nic_vlan_ctx *)cmd_buf->buf; - - vlan_ctx->func_id = func_id; - vlan_ctx->qid = q_id; - vlan_ctx->vlan_tag = vlan_tag; - vlan_ctx->vlan_sel = 0; /* TPID0 in IPSU */ - vlan_ctx->vlan_mode = add ? - NIC_QINQ_INSERT_ENABLE : NIC_CVLAN_INSERT_ENABLE; - - sphw_cpu_to_be32(vlan_ctx, sizeof(struct nic_vlan_ctx)); - - err = sphw_cmdq_direct_resp(nic_cfg->hwdev, SPHW_MOD_L2NIC, SPNIC_UCODE_CMD_MODIFY_VLAN_CTX, - cmd_buf, &out_param, 0, SPHW_CHANNEL_NIC); - - sphw_free_cmd_buf(nic_cfg->hwdev, cmd_buf); - - if (err || out_param != 0) { - nic_err(nic_cfg->dev_hdl, "Failed to set vlan context, err: %d, out_param: 0x%llx\n", - err, out_param); - return -EFAULT; - } - - return err; -} - -int spnic_cfg_vf_vlan(struct spnic_nic_cfg *nic_cfg, u8 opcode, u16 vid, u8 qos, int vf_id) -{ - struct spnic_cmd_vf_vlan_config vf_vlan; - u16 out_size = sizeof(vf_vlan); - u16 glb_func_id; - int err; - u16 vlan_tag; - - /* VLAN 0 is a special case, don't allow it to be removed */ - if (!vid && opcode == SPNIC_CMD_OP_DEL) - return 0; - - memset(&vf_vlan, 0, sizeof(vf_vlan)); - - vf_vlan.opcode = opcode; - vf_vlan.func_id = sphw_glb_pf_vf_offset(nic_cfg->hwdev) + (u16)vf_id; - vf_vlan.vlan_id = vid; - vf_vlan.qos = qos; - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_CFG_VF_VLAN, - &vf_vlan, sizeof(vf_vlan), &vf_vlan, &out_size); - if (err || !out_size || vf_vlan.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set VF %d vlan, err: %d, status: 0x%x,out size: 0x%x\n", - HW_VF_ID_TO_OS(vf_id), err, vf_vlan.msg_head.status, out_size); - return -EFAULT; - } - - vlan_tag = vid + (u16)(qos << VLAN_PRIO_SHIFT); - - glb_func_id = sphw_glb_pf_vf_offset(nic_cfg->hwdev) + (u16)vf_id; - err = spnic_set_vlan_ctx(nic_cfg, glb_func_id, vlan_tag, NIC_CONFIG_ALL_QUEUE_VLAN_CTX, - opcode == SPNIC_CMD_OP_ADD); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to set VF %d vlan ctx, err: %d\n", - HW_VF_ID_TO_OS(vf_id), err); - - /* rollback vlan config */ - if (opcode == SPNIC_CMD_OP_DEL) - vf_vlan.opcode = SPNIC_CMD_OP_ADD; - else - vf_vlan.opcode = SPNIC_CMD_OP_DEL; - l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_CFG_VF_VLAN, &vf_vlan, - sizeof(vf_vlan), &vf_vlan, &out_size); - return err; - } - - return 0; -} - -/* this function just be called by spnic_ndo_set_vf_mac, - * others are not permitted. - */ -int spnic_set_vf_mac(void *hwdev, int vf, unsigned char *mac_addr) -{ - struct vf_data_storage *vf_info; - struct spnic_nic_cfg *nic_cfg; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - vf_info = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf); - - /* duplicate request, so just return success */ - if (ether_addr_equal(vf_info->user_mac_addr, mac_addr)) - return 0; - - ether_addr_copy(vf_info->user_mac_addr, mac_addr); - - return 0; -} - -int spnic_add_vf_vlan(void *hwdev, int vf_id, u16 vlan, u8 qos) -{ - struct spnic_nic_cfg *nic_cfg; - int err; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - err = spnic_cfg_vf_vlan(nic_cfg, SPNIC_CMD_OP_ADD, vlan, qos, vf_id); - if (err) - return err; - - nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan = vlan; - nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos = qos; - - nic_info(nic_cfg->dev_hdl, "Setting VLAN %u, QOS 0x%x on VF %d\n", - vlan, qos, HW_VF_ID_TO_OS(vf_id)); - - return 0; -} - -int spnic_kill_vf_vlan(void *hwdev, int vf_id) -{ - struct vf_data_storage *vf_infos; - struct spnic_nic_cfg *nic_cfg; - int err; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - vf_infos = nic_cfg->vf_infos; - - err = spnic_cfg_vf_vlan(nic_cfg, SPNIC_CMD_OP_DEL, vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan, - vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos, vf_id); - if (err) - return err; - - nic_info(nic_cfg->dev_hdl, "Remove VLAN %u on VF %d\n", - vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan, HW_VF_ID_TO_OS(vf_id)); - - vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan = 0; - vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos = 0; - - return 0; -} - -u16 spnic_vf_info_vlanprio(void *hwdev, int vf_id) -{ - struct spnic_nic_cfg *nic_cfg; - u16 pf_vlan, vlanprio; - u8 pf_qos; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - pf_vlan = nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan; - pf_qos = nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos; - vlanprio = (u16)(pf_vlan | pf_qos << SPNIC_VLAN_PRIORITY_SHIFT); - - return vlanprio; -} - -int spnic_set_vf_link_state(void *hwdev, u16 vf_id, int link) -{ - struct spnic_nic_cfg *nic_cfg = - sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - struct vf_data_storage *vf_infos = nic_cfg->vf_infos; - u8 link_status = 0; - - switch (link) { - case SPNIC_IFLA_VF_LINK_STATE_AUTO: - vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = false; - vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = nic_cfg->link_status ? true : false; - link_status = nic_cfg->link_status; - break; - case SPNIC_IFLA_VF_LINK_STATE_ENABLE: - vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = true; - vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = true; - link_status = SPNIC_LINK_UP; - break; - case SPNIC_IFLA_VF_LINK_STATE_DISABLE: - vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = true; - vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = false; - link_status = SPNIC_LINK_DOWN; - break; - default: - return -EINVAL; - } - - /* Notify the VF of its new link state */ - spnic_notify_vf_link_status(nic_cfg, vf_id, link_status); - - return 0; -} - -int spnic_set_vf_spoofchk(void *hwdev, u16 vf_id, bool spoofchk) -{ - struct spnic_cmd_spoofchk_set spoofchk_cfg; - struct vf_data_storage *vf_infos = NULL; - u16 out_size = sizeof(spoofchk_cfg); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - vf_infos = nic_cfg->vf_infos; - - memset(&spoofchk_cfg, 0, sizeof(spoofchk_cfg)); - - spoofchk_cfg.func_id = sphw_glb_pf_vf_offset(hwdev) + vf_id; - spoofchk_cfg.state = spoofchk ? 1 : 0; - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_SET_SPOOPCHK_STATE, - &spoofchk_cfg, sizeof(spoofchk_cfg), &spoofchk_cfg, &out_size); - if (err || !out_size || spoofchk_cfg.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set VF(%d) spoofchk, err: %d, status: 0x%x, out size: 0x%x\n", - HW_VF_ID_TO_OS(vf_id), err, spoofchk_cfg.msg_head.status, out_size); - err = -EINVAL; - } - - vf_infos[HW_VF_ID_TO_OS(vf_id)].spoofchk = spoofchk; - - return err; -} - -bool spnic_vf_info_spoofchk(void *hwdev, int vf_id) -{ - struct spnic_nic_cfg *nic_cfg; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - return nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].spoofchk; -} - -int spnic_set_vf_trust(void *hwdev, u16 vf_id, bool trust) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (vf_id > nic_cfg->max_vfs) - return -EINVAL; - - nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].trust = trust; - - return 0; -} - -bool spnic_get_vf_trust(void *hwdev, int vf_id) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (vf_id > nic_cfg->max_vfs) - return -EINVAL; - - return nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].trust; -} - -static int spnic_cfg_vf_qps(struct spnic_nic_cfg *nic_cfg, u8 opcode, u16 vf_id, u16 num_qps) -{ - struct spnic_cmd_cfg_qps qps_info; - u16 out_size = sizeof(qps_info); - int err; - - memset(&qps_info, 0, sizeof(qps_info)); - - qps_info.func_id = sphw_glb_pf_vf_offset(nic_cfg->hwdev) + vf_id; - qps_info.opcode = opcode; - qps_info.num_qps = num_qps; - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_CFG_FLEX_QUEUE, &qps_info, - sizeof(qps_info), &qps_info, &out_size); - if (err || !out_size || qps_info.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to %s VF(%d) qps, err: %d, status: 0x%x, out size: 0x%x\n", - opcode == SPNIC_CMD_OP_ALLOC ? "alloc" : "free", - HW_VF_ID_TO_OS(vf_id), err, qps_info.msg_head.status, out_size); - return -EFAULT; - } - - return 0; -} - -int spnic_alloc_vf_qps(void *hwdev, u16 vf_id, u16 num_qps) -{ - struct vf_data_storage *vf_infos = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (vf_id > nic_cfg->max_vfs) - return -EINVAL; - - err = spnic_cfg_vf_qps(nic_cfg, SPNIC_CMD_OP_ALLOC, vf_id, num_qps); - if (err) - return err; - - vf_infos = nic_cfg->vf_infos; - vf_infos[HW_VF_ID_TO_OS(vf_id)].num_qps = num_qps; - - return 0; -} - -int spnic_free_vf_qps(void *hwdev, u16 vf_id) -{ - struct vf_data_storage *vf_infos = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (vf_id > nic_cfg->max_vfs) - return -EINVAL; - - vf_infos = nic_cfg->vf_infos; - err = spnic_cfg_vf_qps(nic_cfg, SPNIC_CMD_OP_FREE, vf_id, - vf_infos[HW_VF_ID_TO_OS(vf_id)].num_qps); - if (err) - return err; - - vf_infos[HW_VF_ID_TO_OS(vf_id)].num_qps = 0; - - return 0; -} - -static int spnic_set_vf_tx_rate_max_min(struct spnic_nic_cfg *nic_cfg, u16 vf_id, - u32 max_rate, u32 min_rate) -{ - struct spnic_cmd_tx_rate_cfg rate_cfg; - u16 out_size = sizeof(rate_cfg); - int err; - - memset(&rate_cfg, 0, sizeof(rate_cfg)); - - rate_cfg.func_id = sphw_glb_pf_vf_offset(nic_cfg->hwdev) + vf_id; - rate_cfg.max_rate = max_rate; - rate_cfg.min_rate = min_rate; - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_SET_MAX_MIN_RATE, - &rate_cfg, sizeof(rate_cfg), &rate_cfg, &out_size); - if (rate_cfg.msg_head.status || err || !out_size) { - nic_err(nic_cfg->dev_hdl, "Failed to set VF %d max rate %u, min rate %u, err: %d, status: 0x%x, out size: 0x%x\n", - HW_VF_ID_TO_OS(vf_id), max_rate, min_rate, err, - rate_cfg.msg_head.status, out_size); - return -EIO; - } - - return 0; -} - -int spnic_set_vf_tx_rate(void *hwdev, u16 vf_id, u32 max_rate, u32 min_rate) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - err = spnic_set_vf_tx_rate_max_min(nic_cfg, vf_id, max_rate, min_rate); - if (err) - return err; - - nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].max_rate = max_rate; - nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].min_rate = min_rate; - - return 0; -} - -void spnic_get_vf_config(void *hwdev, u16 vf_id, struct ifla_vf_info *ivi) -{ - struct vf_data_storage *vfinfo; - struct spnic_nic_cfg *nic_cfg; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - vfinfo = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf_id); - - ivi->vf = HW_VF_ID_TO_OS(vf_id); - ether_addr_copy(ivi->mac, vfinfo->user_mac_addr); - ivi->vlan = vfinfo->pf_vlan; - ivi->qos = vfinfo->pf_qos; - - ivi->spoofchk = vfinfo->spoofchk; - - ivi->trusted = vfinfo->trust; - - ivi->max_tx_rate = vfinfo->max_rate; - ivi->min_tx_rate = vfinfo->min_rate; - - if (!vfinfo->link_forced) - ivi->linkstate = IFLA_VF_LINK_STATE_AUTO; - else if (vfinfo->link_up) - ivi->linkstate = IFLA_VF_LINK_STATE_ENABLE; - else - ivi->linkstate = IFLA_VF_LINK_STATE_DISABLE; -} - -static int spnic_init_vf_infos(struct spnic_nic_cfg *nic_cfg, u16 vf_id) -{ - struct vf_data_storage *vf_infos = nic_cfg->vf_infos; - u8 vf_link_state; - - if (set_vf_link_state > SPNIC_IFLA_VF_LINK_STATE_DISABLE) { - nic_warn(nic_cfg->dev_hdl, "Module Parameter set_vf_link_state value %u is out of range, resetting to %d\n", - set_vf_link_state, SPNIC_IFLA_VF_LINK_STATE_AUTO); - set_vf_link_state = SPNIC_IFLA_VF_LINK_STATE_AUTO; - } - - vf_link_state = set_vf_link_state; - - switch (vf_link_state) { - case SPNIC_IFLA_VF_LINK_STATE_AUTO: - vf_infos[vf_id].link_forced = false; - break; - case SPNIC_IFLA_VF_LINK_STATE_ENABLE: - vf_infos[vf_id].link_forced = true; - vf_infos[vf_id].link_up = true; - break; - case SPNIC_IFLA_VF_LINK_STATE_DISABLE: - vf_infos[vf_id].link_forced = true; - vf_infos[vf_id].link_up = false; - break; - default: - nic_err(nic_cfg->dev_hdl, "Input parameter set_vf_link_state error: %u\n", - vf_link_state); - return -EINVAL; - } - - return 0; -} - -static int vf_func_register(struct spnic_nic_cfg *nic_cfg) -{ - struct spnic_cmd_register_vf register_info; - u16 out_size = sizeof(register_info); - int err; - - err = sphw_register_vf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC, nic_cfg, - spnic_vf_event_handler); - if (err) - return err; - - err = sphw_register_vf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_HILINK, nic_cfg, - spnic_vf_mag_event_handler); - if (err) - goto reg_hilink_err; - - memset(®ister_info, 0, sizeof(register_info)); - register_info.op_register = 1; - err = sphw_mbox_to_pf(nic_cfg->hwdev, SPHW_MOD_L2NIC, SPNIC_NIC_CMD_VF_REGISTER, - ®ister_info, sizeof(register_info), ®ister_info, &out_size, 0, - SPHW_CHANNEL_NIC); - if (err || !out_size || register_info.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to register VF, err: %d, status: 0x%x, out size: 0x%x\n", - err, register_info.msg_head.status, out_size); - err = -EIO; - goto register_err; - } - - return 0; - -register_err: - sphw_unregister_vf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_HILINK); - -reg_hilink_err: - sphw_unregister_vf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC); - - return err; -} - -static int pf_init_vf_infos(struct spnic_nic_cfg *nic_cfg) -{ - u32 size; - int err; - u16 i; - - err = sphw_register_mgmt_msg_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC, nic_cfg, - spnic_pf_event_handler); - if (err) - return err; - - err = sphw_register_mgmt_msg_cb(nic_cfg->hwdev, SPHW_MOD_HILINK, nic_cfg, - spnic_pf_mag_event_handler); - if (err) - goto register_mag_mgmt_cb_err; - - nic_cfg->max_vfs = sphw_func_max_vf(nic_cfg->hwdev); - size = sizeof(*nic_cfg->vf_infos) * nic_cfg->max_vfs; - if (!size) - return 0; - - nic_cfg->vf_infos = kzalloc(size, GFP_KERNEL); - if (!nic_cfg->vf_infos) { - err = -ENOMEM; - goto alloc_vf_infos_err; - } - - for (i = 0; i < nic_cfg->max_vfs; i++) { - err = spnic_init_vf_infos(nic_cfg, i); - if (err) - goto init_vf_infos_err; - } - - err = sphw_register_pf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC, nic_cfg, - spnic_pf_mbox_handler); - if (err) - goto register_nic_mbox_cb_err; - - err = sphw_register_pf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_HILINK, nic_cfg, - spnic_pf_mag_mbox_handler); - if (err) - goto register_mag_mbox_cb_err; - - return 0; - -register_mag_mbox_cb_err: - sphw_unregister_pf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC); - -register_nic_mbox_cb_err: -init_vf_infos_err: - kfree(nic_cfg->vf_infos); - -alloc_vf_infos_err: - sphw_unregister_mgmt_msg_cb(nic_cfg->hwdev, SPHW_MOD_HILINK); - -register_mag_mgmt_cb_err: - sphw_unregister_mgmt_msg_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC); - - return err; -} - -int spnic_vf_func_init(struct spnic_nic_cfg *nic_cfg) -{ - if (sphw_func_type(nic_cfg->hwdev) == TYPE_VF) - return vf_func_register(nic_cfg); - - return pf_init_vf_infos(nic_cfg); -} - -void spnic_vf_func_free(struct spnic_nic_cfg *nic_cfg) -{ - struct spnic_cmd_register_vf unregister; - u16 out_size = sizeof(unregister); - int err; - - memset(&unregister, 0, sizeof(unregister)); - unregister.op_register = 0; - if (sphw_func_type(nic_cfg->hwdev) == TYPE_VF) { - err = sphw_mbox_to_pf(nic_cfg->hwdev, SPHW_MOD_L2NIC, SPNIC_NIC_CMD_VF_REGISTER, - &unregister, sizeof(unregister), &unregister, &out_size, 0, - SPHW_CHANNEL_NIC); - if (err || !out_size || unregister.msg_head.status) - nic_err(nic_cfg->dev_hdl, "Failed to unregister VF, err: %d, status: 0x%x, out_size: 0x%x\n", - err, unregister.msg_head.status, out_size); - - sphw_unregister_vf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC); - sphw_unregister_vf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_HILINK); - } else { - if (nic_cfg->vf_infos) { - sphw_unregister_pf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC); - sphw_unregister_pf_mbox_cb(nic_cfg->hwdev, SPHW_MOD_HILINK); - spnic_clear_vfs_info(nic_cfg->hwdev); - kfree(nic_cfg->vf_infos); - } - - sphw_unregister_mgmt_msg_cb(nic_cfg->hwdev, SPHW_MOD_L2NIC); - sphw_unregister_mgmt_msg_cb(nic_cfg->hwdev, SPHW_MOD_HILINK); - } -} - -static void clear_vf_infos(void *hwdev, u16 vf_id) -{ - struct vf_data_storage *vf_infos; - struct spnic_nic_cfg *nic_cfg; - u16 func_id; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - func_id = sphw_glb_pf_vf_offset(hwdev) + vf_id; - vf_infos = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf_id); - if (vf_infos->use_specified_mac) - spnic_del_mac(hwdev, vf_infos->drv_mac_addr, vf_infos->pf_vlan, - func_id, SPHW_CHANNEL_NIC); - - if (spnic_vf_info_vlanprio(hwdev, vf_id)) - spnic_kill_vf_vlan(hwdev, vf_id); - - if (vf_infos->max_rate) - spnic_set_vf_tx_rate(hwdev, vf_id, 0, 0); - - if (vf_infos->spoofchk) - spnic_set_vf_spoofchk(hwdev, vf_id, false); - - if (vf_infos->trust) - spnic_set_vf_trust(hwdev, vf_id, false); - - memset(vf_infos, 0, sizeof(*vf_infos)); - /* set vf_infos to default */ - spnic_init_vf_infos(nic_cfg, HW_VF_ID_TO_OS(vf_id)); -} - -void spnic_clear_vfs_info(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - u16 i; - - for (i = 0; i < nic_cfg->max_vfs; i++) - clear_vf_infos(hwdev, OS_VF_ID_TO_HW(i)); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cmd.h b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cmd.h deleted file mode 100644 index 689e84d90e97..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_cmd.h +++ /dev/null @@ -1,105 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_NIC_CMD_H -#define SPNIC_NIC_CMD_H - -/* Commands between NIC to MPU - */ -enum spnic_nic_cmd { - SPNIC_NIC_CMD_VF_REGISTER = 0, /* only for PFD and VFD */ - - /* FUNC CFG */ - SPNIC_NIC_CMD_SET_FUNC_TBL = 5, - SPNIC_NIC_CMD_SET_VPORT_ENABLE, - SPNIC_NIC_CMD_SET_RX_MODE, - SPNIC_NIC_CMD_SQ_CI_ATTR_SET, - SPNIC_NIC_CMD_GET_VPORT_STAT, - SPNIC_NIC_CMD_CLEAN_VPORT_STAT, - SPNIC_NIC_CMD_CLEAR_QP_RESOURCE, - SPNIC_NIC_CMD_CFG_FLEX_QUEUE, - /* LRO CFG */ - SPNIC_NIC_CMD_CFG_RX_LRO, - SPNIC_NIC_CMD_CFG_LRO_TIMER, - SPNIC_NIC_CMD_FEATURE_NEGO, - - /* MAC & VLAN CFG */ - SPNIC_NIC_CMD_GET_MAC = 20, - SPNIC_NIC_CMD_SET_MAC, - SPNIC_NIC_CMD_DEL_MAC, - SPNIC_NIC_CMD_UPDATE_MAC, - SPNIC_NIC_CMD_GET_ALL_DEFAULT_MAC, - - SPNIC_NIC_CMD_CFG_FUNC_VLAN, - SPNIC_NIC_CMD_SET_VLAN_FILTER_EN, - SPNIC_NIC_CMD_SET_RX_VLAN_OFFLOAD, - - /* SR-IOV */ - SPNIC_NIC_CMD_CFG_VF_VLAN = 40, - SPNIC_NIC_CMD_SET_SPOOPCHK_STATE, - /* RATE LIMIT */ - SPNIC_NIC_CMD_SET_MAX_MIN_RATE, - - /* RSS CFG */ - SPNIC_NIC_CMD_RSS_CFG = 60, - SPNIC_NIC_CMD_RSS_TEMP_MGR, - SPNIC_NIC_CMD_GET_RSS_CTX_TBL, - SPNIC_NIC_CMD_CFG_RSS_HASH_KEY, - SPNIC_NIC_CMD_CFG_RSS_HASH_ENGINE, - SPNIC_NIC_CMD_GET_INDIR_TBL, - - /* DPI/FDIR */ - SPNIC_NIC_CMD_ADD_TC_FLOW = 80, - SPNIC_NIC_CMD_DEL_TC_FLOW, - SPNIC_NIC_CMD_GET_TC_FLOW, - SPNIC_NIC_CMD_FLUSH_TCAM, - SPNIC_NIC_CMD_CFG_TCAM_BLOCK, - SPNIC_NIC_CMD_ENABLE_TCAM, - SPNIC_NIC_CMD_GET_TCAM_BLOCK, - SPNIC_NIC_CMD_CFG_DPI_TABLE_ID, - - /* PORT CFG */ - SPNIC_NIC_CMD_SET_PORT_ENABLE = 100, - SPNIC_NIC_CMD_CFG_PAUSE_INFO, - - SPNIC_NIC_CMD_SET_PORT_CAR, - SPNIC_NIC_CMD_SET_ER_DROP_PKT, - - SPNIC_NIC_CMD_VF_COS, - SPNIC_NIC_CMD_SETUP_COS_MAPPING, - SPNIC_NIC_CMD_SET_ETS, - SPNIC_NIC_CMD_SET_PFC, - - SPNIC_NIC_CMD_TX_PAUSE_EXCP_NOTICE = 118, - SPNIC_NIC_CMD_INQUIRT_PAUSE_CFG = 119, - - /* MISC */ - SPNIC_NIC_CMD_BIOS_CFG = 120, - SPNIC_NIC_CMD_SET_FIRMWARE_CUSTOM_PACKETS_MSG, - - /* DFX */ - SPNIC_NIC_CMD_GET_SM_TABLE = 140, - SPNIC_NIC_CMD_RD_LINE_TBL, - - SPNIC_NIC_CMD_SET_VHD_CFG = 161, - - SPNIC_NIC_CMD_MAX = 256, -}; - -/* NIC CMDQ MODE */ -enum spnic_ucode_cmd { - SPNIC_UCODE_CMD_MODIFY_QUEUE_CTX = 0, - SPNIC_UCODE_CMD_CLEAN_QUEUE_CONTEXT, - SPNIC_UCODE_CMD_ARM_SQ, - SPNIC_UCODE_CMD_ARM_RQ, - SPNIC_UCODE_CMD_SET_RSS_INDIR_TABLE, - SPNIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE, - SPNIC_UCODE_CMD_GET_RSS_INDIR_TABLE, - SPNIC_UCODE_CMD_GET_RSS_CONTEXT_TABLE, - SPNIC_UCODE_CMD_SET_IQ_ENABLE, - SPNIC_UCODE_CMD_SET_RQ_FLUSH = 10, - SPNIC_UCODE_CMD_MODIFY_VLAN_CTX, - SPNIC_UCODE_CMD_DPI_HASH_TABLE, -}; - -#endif /* SPNIC_NIC_CMD_H */ diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dbg.c b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dbg.c deleted file mode 100644 index 08fe958a6d00..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dbg.c +++ /dev/null @@ -1,151 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/types.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_mt.h" -#include "spnic_nic_qp.h" -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic.h" - -int spnic_dbg_get_wqe_info(void *hwdev, u16 q_id, u16 idx, u16 wqebb_cnt, - u8 *wqe, u16 *wqe_size, enum spnic_queue_type q_type) -{ - struct spnic_io_queue *queue = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - void *src_wqebb = NULL; - u32 i, offset; - - if (!hwdev) { - pr_err("hwdev is NULL.\n"); - return -EINVAL; - } - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if (q_id >= nic_cfg->num_qps) { - pr_err("q_id[%u] > num_qps_cfg[%u].\n", q_id, nic_cfg->num_qps); - return -EINVAL; - } - - queue = (q_type == SPNIC_SQ) ? &nic_cfg->sq[q_id] : &nic_cfg->rq[q_id]; - - if ((idx + wqebb_cnt) > queue->wq.q_depth) { - pr_err("(idx[%u] + idx[%u]) > q_depth[%u].\n", - idx, wqebb_cnt, queue->wq.q_depth); - return -EINVAL; - } - - if (*wqe_size != (queue->wq.wqebb_size * wqebb_cnt)) { - pr_err("Unexpect out buf size from user :%u, expect: %d\n", - *wqe_size, (queue->wq.wqebb_size * wqebb_cnt)); - return -EINVAL; - } - - for (i = 0; i < wqebb_cnt; i++) { - src_wqebb = sphw_wq_wqebb_addr(&queue->wq, WQ_MASK_IDX(&queue->wq, idx + i)); - offset = queue->wq.wqebb_size * i; - memcpy(wqe + offset, src_wqebb, queue->wq.wqebb_size); - } - - return 0; -} - -int spnic_dbg_get_sq_info(void *hwdev, u16 q_id, struct nic_sq_info *sq_info, u32 msg_size) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_io_queue *sq = NULL; - - if (!hwdev || !sq_info) { - pr_err("hwdev or sq_info is NULL.\n"); - return -EINVAL; - } - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if (q_id >= nic_cfg->num_qps) { - nic_err(nic_cfg->dev_hdl, "Input queue id(%u) is larger than the actual queue number\n", - q_id); - return -EINVAL; - } - - if (msg_size != sizeof(*sq_info)) { - nic_err(nic_cfg->dev_hdl, "Unexpect out buf size from user :%u, expect: %lu\n", - msg_size, sizeof(*sq_info)); - return -EINVAL; - } - - sq = &nic_cfg->sq[q_id]; - - sq_info->q_id = q_id; - sq_info->pi = spnic_get_sq_local_pi(sq); - sq_info->ci = spnic_get_sq_local_ci(sq); - sq_info->fi = spnic_get_sq_hw_ci(sq); - sq_info->q_depth = sq->wq.q_depth; - sq_info->wqebb_size = sq->wq.wqebb_size; - - sq_info->ci_addr = sq->tx.cons_idx_addr; - - sq_info->cla_addr = sq->wq.wq_block_paddr; - sq_info->slq_handle = sq; - - sq_info->doorbell.map_addr = (u64 *)sq->db_addr; - - return 0; -} - -int spnic_dbg_get_rq_info(void *hwdev, u16 q_id, struct nic_rq_info *rq_info, u32 msg_size) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_io_queue *rq = NULL; - - if (!hwdev || !rq_info) { - pr_err("hwdev or rq_info is NULL.\n"); - return -EINVAL; - } - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if (q_id >= nic_cfg->num_qps) { - nic_err(nic_cfg->dev_hdl, "Input queue id(%u) is larger than the actual queue number\n", - q_id); - return -EINVAL; - } - - if (msg_size != sizeof(*rq_info)) { - nic_err(nic_cfg->dev_hdl, "Unexpect out buf size from user: %u, expect: %lu\n", - msg_size, sizeof(*rq_info)); - return -EINVAL; - } - - rq = &nic_cfg->rq[q_id]; - - rq_info->q_id = q_id; - - rq_info->hw_pi = cpu_to_be16(*rq->rx.pi_virt_addr); - rq_info->ci = spnic_get_rq_local_ci(rq); - - rq_info->sw_pi = 0; - - rq_info->wqebb_size = rq->wq.wqebb_size; - rq_info->q_depth = (u16)rq->wq.q_depth; - - rq_info->buf_len = nic_cfg->rx_buff_len; - - rq_info->slq_handle = rq; - - rq_info->ci_wqe_page_addr = sphw_wq_get_first_wqe_page_addr(&rq->wq); - rq_info->ci_cla_tbl_addr = rq->wq.wq_block_paddr; - - rq_info->msix_idx = rq->msix_entry_idx; - rq_info->msix_vector = 0; - - return 0; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dbg.h b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dbg.h deleted file mode 100644 index d86c65ed5f4f..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dbg.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_NIC_DBG_H -#define SPNIC_NIC_DBG_H - -#include "spnic_nic_io.h" - -int spnic_dbg_get_sq_info(void *hwdev, u16 q_id, struct nic_sq_info *sq_info, u32 msg_size); - -int spnic_dbg_get_rq_info(void *hwdev, u16 q_id, struct nic_rq_info *rq_info, u32 msg_size); - -int spnic_dbg_get_wqe_info(void *hwdev, u16 q_id, u16 idx, u16 wqebb_cnt, - u8 *wqe, u16 *wqe_size, enum spnic_queue_type q_type); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dev.h b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dev.h deleted file mode 100644 index 8a0708fda19a..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_dev.h +++ /dev/null @@ -1,354 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_NIC_DEV_H -#define SPNIC_NIC_DEV_H - -#include <linux/netdevice.h> -#include <linux/semaphore.h> -#include <linux/types.h> -#include <linux/bitops.h> - -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_tx.h" -#include "spnic_rx.h" -#include "spnic_dcb.h" - -#define SPNIC_NIC_DRV_NAME "spnic" -#define SPNIC_DRV_VERSION "B090" -#define SPNIC_DRV_DESC "Ramaxel(R) Network Interface Card Driver" - -#define SPNIC_FUNC_IS_VF(hwdev) (sphw_func_type(hwdev) == TYPE_VF) - -#define SPNIC_AVG_PKT_SMALL 256U -#define SPNIC_MODERATONE_DELAY HZ - -#define LP_PKT_CNT 64 - -enum spnic_flags { - SPNIC_INTF_UP, - SPNIC_MAC_FILTER_CHANGED, - SPNIC_LP_TEST, - SPNIC_RSS_ENABLE, - SPNIC_DCB_ENABLE, - SPNIC_SAME_RXTX, - SPNIC_INTR_ADAPT, - SPNIC_UPDATE_MAC_FILTER, - SPNIC_CHANGE_RES_INVALID, - SPNIC_RSS_DEFAULT_INDIR, -}; - -#define SPHW_CHANNEL_RES_VALID(nic_dev) \ - (test_bit(SPNIC_INTF_UP, &(nic_dev)->flags) && \ - !test_bit(SPNIC_CHANGE_RES_INVALID, &(nic_dev)->flags)) - -#define RX_BUFF_NUM_PER_PAGE 2 - -#define VLAN_BITMAP_BYTE_SIZE(nic_dev) (sizeof(*(nic_dev)->vlan_bitmap)) -#define VLAN_BITMAP_BITS_SIZE(nic_dev) (VLAN_BITMAP_BYTE_SIZE(nic_dev) * 8) -#define VLAN_NUM_BITMAPS(nic_dev) (VLAN_N_VID / \ - VLAN_BITMAP_BITS_SIZE(nic_dev)) -#define VLAN_BITMAP_SIZE(nic_dev) (VLAN_N_VID / \ - VLAN_BITMAP_BYTE_SIZE(nic_dev)) -#define VID_LINE(nic_dev, vid) ((vid) / VLAN_BITMAP_BITS_SIZE(nic_dev)) -#define VID_COL(nic_dev, vid) ((vid) & (VLAN_BITMAP_BITS_SIZE(nic_dev) - 1)) - -#define SPNIC_DRV_FEATURE NIC_F_ALL_MASK - -enum spnic_event_work_flags { - EVENT_WORK_TX_TIMEOUT, -}; - -enum spnic_rx_mode_state { - SPNIC_HW_PROMISC_ON, - SPNIC_HW_ALLMULTI_ON, - SPNIC_PROMISC_FORCE_ON, - SPNIC_ALLMULTI_FORCE_ON, -}; - -enum mac_filter_state { - SPNIC_MAC_WAIT_HW_SYNC, - SPNIC_MAC_HW_SYNCED, - SPNIC_MAC_WAIT_HW_UNSYNC, - SPNIC_MAC_HW_UNSYNCED, -}; - -struct spnic_mac_filter { - struct list_head list; - u8 addr[ETH_ALEN]; - unsigned long state; -}; - -struct spnic_irq { - struct net_device *netdev; - /* IRQ corresponding index number */ - u16 msix_entry_idx; - u32 irq_id; /* The IRQ number from OS */ - char irq_name[IFNAMSIZ + 16]; - struct napi_struct napi; - cpumask_t affinity_mask; - struct spnic_txq *txq; - struct spnic_rxq *rxq; -}; - -struct spnic_intr_coal_info { - u8 pending_limt; - u8 coalesce_timer_cfg; - u8 resend_timer_cfg; - - u64 pkt_rate_low; - u8 rx_usecs_low; - u8 rx_pending_limt_low; - u64 pkt_rate_high; - u8 rx_usecs_high; - u8 rx_pending_limt_high; - - u8 user_set_intr_coal_flag; -}; - -struct spnic_dyna_txrxq_params { - u16 num_qps; - u16 num_rss; - u16 rss_limit; - u8 num_tc; - u8 rsvd1; - u32 sq_depth; - u32 rq_depth; - - struct spnic_dyna_txq_res *txqs_res; - struct spnic_dyna_rxq_res *rxqs_res; - struct spnic_irq *irq_cfg; -}; - -#define SPNIC_NIC_STATS_INC(nic_dev, field) \ -do { \ - u64_stats_update_begin(&(nic_dev)->stats.syncp);\ - (nic_dev)->stats.field++; \ - u64_stats_update_end(&(nic_dev)->stats.syncp); \ -} while (0) - -struct spnic_nic_stats { - u64 netdev_tx_timeout; - - /* Subdivision statistics show in private tool */ - u64 tx_carrier_off_drop; - u64 tx_invalid_qid; - - struct u64_stats_sync syncp; -}; - -#define SPNIC_TCAM_DYNAMIC_BLOCK_SIZE 16 -#define SPNIC_MAX_TCAM_FILTERS 512 - -#define SPNIC_PKT_TCAM_DYNAMIC_INDEX_START(block_index) \ - (SPNIC_TCAM_DYNAMIC_BLOCK_SIZE * (block_index)) - -struct spnic_rx_flow_rule { - struct list_head rules; - int tot_num_rules; -}; - -struct spnic_tcam_dynamic_block { - struct list_head block_list; - u16 dynamic_block_id; - u16 dynamic_index_cnt; - u8 dynamic_index_used[SPNIC_TCAM_DYNAMIC_BLOCK_SIZE]; -}; - -struct spnic_tcam_dynamic_block_info { - struct list_head tcam_dynamic_list; - u16 dynamic_block_cnt; -}; - -struct spnic_tcam_filter { - struct list_head tcam_filter_list; - u16 dynamic_block_id; - u16 index; - struct tag_tcam_key tcam_key; - u16 queue; -}; - -/* function level struct info */ -struct spnic_tcam_info { - u16 tcam_rule_nums; - struct list_head tcam_list; - struct spnic_tcam_dynamic_block_info tcam_dynamic_info; -}; - -struct spnic_nic_dev { - struct pci_dev *pdev; - struct net_device *netdev; - void *hwdev; - - int poll_weight; - - unsigned long *vlan_bitmap; - - u16 max_qps; - - u32 msg_enable; - unsigned long flags; - - u32 lro_replenish_thld; - u32 dma_rx_buff_size; - u16 rx_buff_len; - u32 page_order; - - /* Rss related varibles */ - u8 rss_hash_engine; - struct nic_rss_type rss_type; - u8 *rss_hkey; - /* hkey in big endian */ - u32 *rss_hkey_be; - u32 *rss_indir; - - u32 dcb_changes; - struct spnic_dcb_config hw_dcb_cfg; - struct spnic_dcb_config wanted_dcb_cfg; - unsigned long dcb_flags; - int disable_port_cnt; - /* lock for disable or enable traffic flow */ - struct semaphore dcb_sem; - - struct spnic_intr_coal_info *intr_coalesce; - unsigned long last_moder_jiffies; - u32 adaptive_rx_coal; - u8 intr_coal_set_flag; - - struct spnic_nic_stats stats; - - /* lock for nic resource */ - struct mutex nic_mutex; - bool force_port_disable; - struct semaphore port_state_sem; - u8 link_status; - - struct nic_service_cap nic_cap; - - struct spnic_txq *txqs; - struct spnic_rxq *rxqs; - struct spnic_dyna_txrxq_params q_params; - - u16 num_qp_irq; - struct irq_info *qps_irq_info; - - struct workqueue_struct *workq; - - struct work_struct rx_mode_work; - struct delayed_work moderation_task; - - struct list_head uc_filter_list; - struct list_head mc_filter_list; - unsigned long rx_mod_state; - int netdev_uc_cnt; - int netdev_mc_cnt; - - int lb_test_rx_idx; - int lb_pkt_len; - u8 *lb_test_rx_buf; - - struct spnic_tcam_info tcam; - struct spnic_rx_flow_rule rx_flow_rule; - - struct bpf_prog *xdp_prog; - - struct delayed_work periodic_work; - /* reference to enum spnic_event_work_flags */ - unsigned long event_flag; -}; - -#define IPSEC_CAP_IS_SUPPORT(nic_dev) ((nic_dev)->ipsec) - -#define spnic_msg(level, nic_dev, msglvl, format, arg...) \ -do { \ - if ((nic_dev)->netdev && (nic_dev)->netdev->reg_state \ - == NETREG_REGISTERED) \ - nicif_##level((nic_dev), msglvl, (nic_dev)->netdev, \ - format, ## arg); \ - else \ - nic_##level(&(nic_dev)->pdev->dev, \ - format, ## arg); \ -} while (0) - -#define spnic_info(nic_dev, msglvl, format, arg...) \ - spnic_msg(info, nic_dev, msglvl, format, ## arg) - -#define spnic_warn(nic_dev, msglvl, format, arg...) \ - spnic_msg(warn, nic_dev, msglvl, format, ## arg) - -#define spnic_err(nic_dev, msglvl, format, arg...) \ - spnic_msg(err, nic_dev, msglvl, format, ## arg) - -#define nicif_err(priv, type, dev, fmt, args...) \ - netif_level(err, priv, type, dev, "[NIC]" fmt, ##args) -#define nicif_warn(priv, type, dev, fmt, args...) \ - netif_level(warn, priv, type, dev, "[NIC]" fmt, ##args) -#define nicif_notice(priv, type, dev, fmt, args...) \ - netif_level(notice, priv, type, dev, "[NIC]" fmt, ##args) -#define nicif_info(priv, type, dev, fmt, args...) \ - netif_level(info, priv, type, dev, "[NIC]" fmt, ##args) -#define nicif_dbg(priv, type, dev, fmt, args...) \ - netif_level(dbg, priv, type, dev, "[NIC]" fmt, ##args) - -extern struct spnic_uld_info nic_uld_info; - -u32 spnic_get_io_stats_size(struct spnic_nic_dev *nic_dev); - -void spnic_get_io_stats(struct spnic_nic_dev *nic_dev, void *stats); - -int spnic_open(struct net_device *netdev); - -int spnic_close(struct net_device *netdev); - -void spnic_set_ethtool_ops(struct net_device *netdev); - -void spnicvf_set_ethtool_ops(struct net_device *netdev); - -int nic_ioctl(void *uld_dev, u32 cmd, const void *buf_in, - u32 in_size, void *buf_out, u32 *out_size); - -void spnic_update_num_qps(struct net_device *netdev); - -int spnic_qps_irq_init(struct spnic_nic_dev *nic_dev); - -void spnic_qps_irq_deinit(struct spnic_nic_dev *nic_dev); - -void spnic_set_netdev_ops(struct spnic_nic_dev *nic_dev); - -int spnic_set_hw_features(struct spnic_nic_dev *nic_dev); - -void spnic_set_rx_mode_work(struct work_struct *work); - -void spnic_clean_mac_list_filter(struct spnic_nic_dev *nic_dev); - -void spnic_get_strings(struct net_device *netdev, u32 stringset, u8 *data); - -void spnic_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, u64 *data); - -int spnic_get_sset_count(struct net_device *netdev, int sset); - -int spnic_force_port_disable(struct spnic_nic_dev *nic_dev); - -int spnic_force_set_port_state(struct spnic_nic_dev *nic_dev, bool enable); - -int spnic_maybe_set_port_state(struct spnic_nic_dev *nic_dev, bool enable); - -int spnic_get_link_ksettings(struct net_device *netdev, - struct ethtool_link_ksettings *link_settings); -int spnic_set_link_ksettings(struct net_device *netdev, - const struct ethtool_link_ksettings *link_settings); - -void spnic_auto_moderation_work(struct work_struct *work); - -typedef void (*spnic_reopen_handler)(struct spnic_nic_dev *nic_dev, const void *priv_data); -int spnic_change_channel_settings(struct spnic_nic_dev *nic_dev, - struct spnic_dyna_txrxq_params *trxq_params, - spnic_reopen_handler reopen_handler, const void *priv_data); - -void spnic_link_status_change(struct spnic_nic_dev *nic_dev, bool status); - -bool spnic_is_xdp_enable(struct spnic_nic_dev *nic_dev); -int spnic_xdp_max_mtu(struct spnic_nic_dev *nic_dev); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_event.c b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_event.c deleted file mode 100644 index 0e8a2c4a3961..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_event.c +++ /dev/null @@ -1,506 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/etherdevice.h> -#include <linux/if_vlan.h> -#include <linux/ethtool.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/netdevice.h> -#include <linux/module.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic.h" -#include "spnic_nic_cmd.h" - -static int spnic_init_vf_config(struct spnic_nic_cfg *nic_cfg, u16 vf_id) -{ - struct vf_data_storage *vf_info; - u16 func_id; - int err = 0; - - vf_info = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf_id); - ether_addr_copy(vf_info->drv_mac_addr, vf_info->user_mac_addr); - if (!is_zero_ether_addr(vf_info->drv_mac_addr)) { - vf_info->use_specified_mac = true; - func_id = sphw_glb_pf_vf_offset(nic_cfg->hwdev) + vf_id; - - err = spnic_set_mac(nic_cfg->hwdev, vf_info->drv_mac_addr, - vf_info->pf_vlan, func_id, SPHW_CHANNEL_NIC); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to set VF %d MAC\n", - HW_VF_ID_TO_OS(vf_id)); - return err; - } - } else { - vf_info->use_specified_mac = false; - } - - if (spnic_vf_info_vlanprio(nic_cfg->hwdev, vf_id)) { - err = spnic_cfg_vf_vlan(nic_cfg, SPNIC_CMD_OP_ADD, - vf_info->pf_vlan, vf_info->pf_qos, vf_id); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to add VF %d VLAN_QOS\n", - HW_VF_ID_TO_OS(vf_id)); - return err; - } - } - - if (vf_info->max_rate) { - err = spnic_set_vf_tx_rate(nic_cfg->hwdev, vf_id, vf_info->max_rate, - vf_info->min_rate); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to set VF %d max rate %u, min rate %u\n", - HW_VF_ID_TO_OS(vf_id), vf_info->max_rate, - vf_info->min_rate); - return err; - } - } - - return 0; -} - -static int register_vf_msg_handler(struct spnic_nic_cfg *nic_cfg, u16 vf_id) -{ - int err; - - if (vf_id > nic_cfg->max_vfs) { - nic_err(nic_cfg->dev_hdl, "Register VF id %d exceed limit[0-%d]\n", - HW_VF_ID_TO_OS(vf_id), HW_VF_ID_TO_OS(nic_cfg->max_vfs)); - return -EFAULT; - } - - err = spnic_init_vf_config(nic_cfg, vf_id); - if (err) - return err; - - nic_cfg->vf_infos[HW_VF_ID_TO_OS(vf_id)].registered = true; - - return 0; -} - -static int unregister_vf_msg_handler(struct spnic_nic_cfg *nic_cfg, u16 vf_id) -{ - struct vf_data_storage *vf_info = - nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf_id); - struct spnic_port_mac_set mac_info; - u16 out_size = sizeof(mac_info); - int err; - - if (vf_id > nic_cfg->max_vfs) - return -EFAULT; - - vf_info->registered = false; - - memset(&mac_info, 0, sizeof(mac_info)); - mac_info.func_id = sphw_glb_pf_vf_offset(nic_cfg->hwdev) + (u16)vf_id; - mac_info.vlan_id = vf_info->pf_vlan; - ether_addr_copy(mac_info.mac, vf_info->drv_mac_addr); - - if (vf_info->use_specified_mac || vf_info->pf_vlan) { - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_DEL_MAC, - &mac_info, sizeof(mac_info), &mac_info, &out_size); - if (err || mac_info.msg_head.status || !out_size) { - nic_err(nic_cfg->dev_hdl, "Failed to delete VF %d MAC, err: %d, status: 0x%x, out size: 0x%x\n", - HW_VF_ID_TO_OS(vf_id), err, - mac_info.msg_head.status, out_size); - return -EFAULT; - } - } - - memset(vf_info->drv_mac_addr, 0, ETH_ALEN); - - return 0; -} - -static int spnic_register_vf_msg_handler(struct spnic_nic_cfg *nic_cfg, - u16 vf_id, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct spnic_cmd_register_vf *register_vf = buf_in; - struct spnic_cmd_register_vf *register_info = buf_out; - int err; - - if (register_vf->op_register) - err = register_vf_msg_handler(nic_cfg, vf_id); - else - err = unregister_vf_msg_handler(nic_cfg, vf_id); - - if (err) - register_info->msg_head.status = EFAULT; - - *out_size = sizeof(*register_info); - - return 0; -} - -static int spnic_get_vf_cos_msg_handler(struct spnic_nic_cfg *nic_cfg, u16 vf_id, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size) -{ - struct spnic_cmd_vf_dcb_state *dcb_state = buf_out; - - memcpy(&dcb_state->state, &nic_cfg->dcb_state, - sizeof(nic_cfg->dcb_state)); - - dcb_state->msg_head.status = 0; - *out_size = sizeof(*dcb_state); - return 0; -} - -static int spnic_get_vf_mac_msg_handler(struct spnic_nic_cfg *nic_cfg, u16 vf, - void *buf_in, u16 in_size, void *buf_out, u16 *out_size) -{ - struct vf_data_storage *vf_info = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf); - struct spnic_port_mac_set *mac_info = buf_out; - - int err; - - if (sphw_support_ovs(nic_cfg->hwdev, NULL)) { - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_GET_MAC, buf_in, - in_size, buf_out, out_size); - if (!err) { - if (is_zero_ether_addr(mac_info->mac)) - ether_addr_copy(mac_info->mac, vf_info->drv_mac_addr); - } - return err; - } - - ether_addr_copy(mac_info->mac, vf_info->drv_mac_addr); - mac_info->msg_head.status = 0; - *out_size = sizeof(*mac_info); - - return 0; -} - -static int spnic_set_vf_mac_msg_handler(struct spnic_nic_cfg *nic_cfg, u16 vf, - void *buf_in, u16 in_size, void *buf_out, u16 *out_size) -{ - struct vf_data_storage *vf_info = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf); - struct spnic_port_mac_set *mac_in = buf_in; - struct spnic_port_mac_set *mac_out = buf_out; - int err; - - if (vf_info->use_specified_mac && !vf_info->trust && - is_valid_ether_addr(mac_in->mac)) { - nic_warn(nic_cfg->dev_hdl, "PF has already set VF %d MAC address, and vf trust is off.\n", - HW_VF_ID_TO_OS(vf)); - mac_out->msg_head.status = SPNIC_PF_SET_VF_ALREADY; - *out_size = sizeof(*mac_out); - return 0; - } - - if (is_valid_ether_addr(mac_in->mac)) - mac_in->vlan_id = vf_info->pf_vlan; - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_SET_MAC, - buf_in, in_size, buf_out, out_size); - if (err || !(*out_size)) { - nic_err(nic_cfg->dev_hdl, "Failed to set VF %d MAC address, err: %d,status: 0x%x, out size: 0x%x\n", - HW_VF_ID_TO_OS(vf), err, mac_out->msg_head.status, - *out_size); - return -EFAULT; - } - - if (is_valid_ether_addr(mac_in->mac) && !mac_out->msg_head.status) - ether_addr_copy(vf_info->drv_mac_addr, mac_in->mac); - - return err; -} - -static int spnic_del_vf_mac_msg_handler(struct spnic_nic_cfg *nic_cfg, u16 vf, - void *buf_in, u16 in_size, void *buf_out, u16 *out_size) -{ - struct vf_data_storage *vf_info = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf); - struct spnic_port_mac_set *mac_in = buf_in; - struct spnic_port_mac_set *mac_out = buf_out; - int err; - - if (vf_info->use_specified_mac && !vf_info->trust && - is_valid_ether_addr(mac_in->mac)) { - nic_warn(nic_cfg->dev_hdl, "PF has already set VF %d MAC address, and vf trust is off.\n", - HW_VF_ID_TO_OS(vf)); - mac_out->msg_head.status = SPNIC_PF_SET_VF_ALREADY; - *out_size = sizeof(*mac_out); - return 0; - } - - if (is_valid_ether_addr(mac_in->mac)) - mac_in->vlan_id = vf_info->pf_vlan; - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_DEL_MAC, - buf_in, in_size, buf_out, out_size); - if (err || !(*out_size)) { - nic_err(nic_cfg->dev_hdl, "Failed to delete VF %d MAC, err: %d, status: 0x%x, out size: 0x%x\n", - HW_VF_ID_TO_OS(vf), err, mac_out->msg_head.status, - *out_size); - return -EFAULT; - } - - if (is_valid_ether_addr(mac_in->mac) && !mac_out->msg_head.status) - eth_zero_addr(vf_info->drv_mac_addr); - - return err; -} - -static int spnic_update_vf_mac_msg_handler(struct spnic_nic_cfg *nic_cfg, - u16 vf, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct vf_data_storage *vf_info = nic_cfg->vf_infos + HW_VF_ID_TO_OS(vf); - struct spnic_port_mac_update *mac_in = buf_in; - struct spnic_port_mac_update *mac_out = buf_out; - int err; - - if (!is_valid_ether_addr(mac_in->new_mac)) { - nic_err(nic_cfg->dev_hdl, "Update VF MAC is invalid.\n"); - return -EINVAL; - } - - if (vf_info->use_specified_mac && !vf_info->trust) { - nic_warn(nic_cfg->dev_hdl, "PF has already set VF %d MAC address, and vf trust is off.\n", - HW_VF_ID_TO_OS(vf)); - mac_out->msg_head.status = SPNIC_PF_SET_VF_ALREADY; - *out_size = sizeof(*mac_out); - return 0; - } - - mac_in->vlan_id = vf_info->pf_vlan; - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_UPDATE_MAC, - buf_in, in_size, buf_out, out_size); - if (err || !(*out_size)) { - nic_warn(nic_cfg->dev_hdl, "Failed to update VF %d MAC, err: %d,status: 0x%x, out size: 0x%x\n", - HW_VF_ID_TO_OS(vf), err, mac_out->msg_head.status, - *out_size); - return -EFAULT; - } - - if (!mac_out->msg_head.status) - ether_addr_copy(vf_info->drv_mac_addr, mac_in->new_mac); - - return err; -} - -const struct vf_msg_handler vf_cmd_handler[] = { - { - .cmd = SPNIC_NIC_CMD_VF_REGISTER, - .handler = spnic_register_vf_msg_handler, - }, - - { - .cmd = SPNIC_NIC_CMD_GET_MAC, - .handler = spnic_get_vf_mac_msg_handler, - }, - - { - .cmd = SPNIC_NIC_CMD_SET_MAC, - .handler = spnic_set_vf_mac_msg_handler, - }, - - { - .cmd = SPNIC_NIC_CMD_DEL_MAC, - .handler = spnic_del_vf_mac_msg_handler, - }, - - { - .cmd = SPNIC_NIC_CMD_UPDATE_MAC, - .handler = spnic_update_vf_mac_msg_handler, - }, - - { - .cmd = SPNIC_NIC_CMD_VF_COS, - .handler = spnic_get_vf_cos_msg_handler - }, -}; - -static int _l2nic_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, - u16 in_size, void *buf_out, u16 *out_size, u16 channel) -{ - u32 i, cmd_cnt = ARRAY_LEN(vf_cmd_handler); - bool cmd_to_pf = false; - - if (sphw_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 sphw_mbox_to_pf(hwdev, SPHW_MOD_L2NIC, cmd, buf_in, in_size, buf_out, - out_size, 0, channel); - - return sphw_msg_to_mgmt_sync(hwdev, SPHW_MOD_L2NIC, cmd, buf_in, in_size, buf_out, - out_size, 0, channel); -} - -int l2nic_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - return _l2nic_msg_to_mgmt_sync(hwdev, cmd, buf_in, in_size, buf_out, - out_size, SPHW_CHANNEL_NIC); -} - -int l2nic_msg_to_mgmt_sync_ch(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size, u16 channel) -{ - return _l2nic_msg_to_mgmt_sync(hwdev, cmd, buf_in, in_size, buf_out, out_size, channel); -} - -/* pf/ppf handler mbox msg from vf */ -int spnic_pf_mbox_handler(void *hwdev, void *pri_handle, - u16 vf_id, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - u32 index, cmd_size = ARRAY_LEN(vf_cmd_handler); - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EFAULT; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - for (index = 0; index < cmd_size; index++) { - if (cmd == vf_cmd_handler[index].cmd) - return vf_cmd_handler[index].handler(nic_cfg, vf_id, buf_in, in_size, - buf_out, out_size); - } - - nic_warn(nic_cfg->dev_hdl, "NO handler for nic cmd(%u) received from vf id: %u\n", - cmd, vf_id); - - return -EINVAL; -} - -void spnic_notify_dcb_state_event(struct spnic_nic_cfg *nic_cfg, struct spnic_dcb_state *dcb_state) -{ - struct sphw_event_info event_info = {0}; - - /* This is 8 user priority to cos mapping relationships */ - sdk_info(nic_cfg->dev_hdl, "DCB %s, default cos %u, up2cos %u%u%u%u%u%u%u%u\n", - dcb_state->dcb_on ? "on" : "off", dcb_state->default_cos, - dcb_state->up_cos[0], dcb_state->up_cos[1], - dcb_state->up_cos[2], dcb_state->up_cos[3], - dcb_state->up_cos[4], dcb_state->up_cos[5], - dcb_state->up_cos[6], dcb_state->up_cos[7]); - - /* Saved in sdk for statefull module */ - spnic_save_dcb_state(nic_cfg, dcb_state); - - event_info.type = SPHW_EVENT_DCB_STATE_CHANGE; - memcpy(&event_info.dcb_state, dcb_state, sizeof(event_info.dcb_state)); - - sphw_event_callback(nic_cfg->hwdev, &event_info); -} - -void dcb_state_event(void *hwdev, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct spnic_cmd_vf_dcb_state *vf_dcb; - struct spnic_nic_cfg *nic_cfg; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - vf_dcb = buf_in; - if (!vf_dcb) - return; - - spnic_notify_dcb_state_event(nic_cfg, &vf_dcb->state); -} - -void tx_pause_excp_event_handler(void *hwdev, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct nic_cmd_tx_pause_notice *excp_info = buf_in; - struct spnic_nic_cfg *nic_cfg = NULL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - if (in_size != sizeof(*excp_info)) { - nic_err(nic_cfg->dev_hdl, "Invalid in_size: %u, should be %ld\n", - in_size, sizeof(*excp_info)); - return; - } - - nic_warn(nic_cfg->dev_hdl, "Receive tx pause exception event, excp: %u, level: %u\n", - excp_info->tx_pause_except, excp_info->except_level); - - sphw_fault_event_report(hwdev, SPHW_FAULT_SRC_TX_PAUSE_EXCP, (u16)excp_info->except_level); -} - -struct nic_event_handler nic_cmd_handler[] = { - { - .cmd = SPNIC_NIC_CMD_VF_COS, - .handler = dcb_state_event, - }, - { - .cmd = SPNIC_NIC_CMD_TX_PAUSE_EXCP_NOTICE, - .handler = tx_pause_excp_event_handler, - }, -}; - -static void _event_handler(void *hwdev, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - u32 size = sizeof(nic_cmd_handler) / sizeof(struct nic_event_handler); - u32 i; - - if (!hwdev) - return; - - *out_size = 0; - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - for (i = 0; i < size; i++) { - if (cmd == nic_cmd_handler[i].cmd) { - nic_cmd_handler[i].handler(hwdev, buf_in, in_size, buf_out, out_size); - break; - } - } - - /* can't find this event cmd */ - if (i == size) - sdk_warn(nic_cfg->dev_hdl, "Unsupported event cmd(%u) to process\n", - cmd); -} - -/* vf handler mbox msg from ppf/pf */ -/* vf link change event - * vf fault report event, TBD - */ -int spnic_vf_event_handler(void *hwdev, void *pri_handle, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - _event_handler(hwdev, cmd, buf_in, in_size, buf_out, out_size); - return 0; -} - -/* pf/ppf handler mgmt cpu report nic event*/ -void spnic_pf_event_handler(void *hwdev, void *pri_handle, u16 cmd, void *buf_in, u16 in_size, - void *buf_out, u16 *out_size) -{ - _event_handler(hwdev, cmd, buf_in, in_size, buf_out, out_size); -} - -u8 spnic_nic_sw_aeqe_handler(void *hwdev, u8 event, u8 *data) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return 0; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - nic_err(nic_cfg->dev_hdl, "Received nic ucode aeq event type: 0x%x, data: 0x%llx\n", - event, *((u64 *)data)); - - return 0; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_io.c b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_io.c deleted file mode 100644 index 3f1fb1381844..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_io.c +++ /dev/null @@ -1,1123 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/types.h> -#include <linux/module.h> - -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "sphw_common.h" -#include "spnic_nic_qp.h" -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic.h" -#include "spnic_nic_cmd.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 - -static unsigned char tx_pending_limit = SPNIC_DEAULT_TX_CI_PENDING_LIMIT; -module_param(tx_pending_limit, byte, 0444); -MODULE_PARM_DESC(tx_pending_limit, "TX CI coalescing parameter pending_limit (default=0)"); - -static unsigned char tx_coalescing_time = SPNIC_DEAULT_TX_CI_COALESCING_TIME; -module_param(tx_coalescing_time, byte, 0444); -MODULE_PARM_DESC(tx_coalescing_time, "TX CI coalescing parameter coalescing_time (default=0)"); - -static unsigned char rq_wqe_type = SPNIC_NORMAL_RQ_WQE; -module_param(rq_wqe_type, byte, 0444); -MODULE_PARM_DESC(rq_wqe_type, "RQ WQE type 0-8Bytes, 1-16Bytes, 2-32Bytes (default=2)"); - -static u32 tx_drop_thd_on = SPNIC_DEAULT_DROP_THD_ON; -module_param(tx_drop_thd_on, uint, 0644); -MODULE_PARM_DESC(tx_drop_thd_on, "TX parameter drop_thd_on (default=0xffff)"); - -static u32 tx_drop_thd_off = SPNIC_DEAULT_DROP_THD_OFF; -module_param(tx_drop_thd_off, uint, 0644); -MODULE_PARM_DESC(tx_drop_thd_off, "TX parameter drop_thd_off (default=0)"); -/* performance: ci addr RTE_CACHE_SIZE(64B) alignment */ -#define SPNIC_CI_Q_ADDR_SIZE 64 - -#define CI_TABLE_SIZE(num_qps, pg_sz) (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) - -#define WQ_PREFETCH_MAX 4 -#define WQ_PREFETCH_MIN 1 -#define WQ_PREFETCH_THRESHOLD 256 - -#define SPNIC_Q_CTXT_MAX 31 /* (2048 - 8) / 64 */ - -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_EN_SHIFT 31 - -#define RQ_CTXT_CEQ_ATTR_INTR_MASK 0x3FFU -#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) (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) - -/* sq and rq */ -#define TOTAL_DB_NUM(num_qps) ((u16)(2 * (num_qps))) - -int spnic_create_sq(struct spnic_nic_cfg *nic_cfg, struct spnic_io_queue *sq, - u16 q_id, u32 sq_depth, u16 sq_msix_idx) -{ - int err; - - /* sq used & hardware request init 1*/ - sq->owner = 1; - - sq->q_id = q_id; - sq->msix_entry_idx = sq_msix_idx; - - err = sphw_wq_create(nic_cfg->hwdev, &sq->wq, sq_depth, (u16)BIT(SPNIC_SQ_WQEBB_SHIFT)); - if (err) { - sdk_err(nic_cfg->dev_hdl, "Failed to create tx queue(%u) wq\n", - q_id); - return err; - } - - return 0; -} - -void spnic_destroy_sq(struct spnic_nic_cfg *nic_cfg, struct spnic_io_queue *sq) -{ - sphw_wq_destroy(&sq->wq); -} - -int spnic_create_rq(struct spnic_nic_cfg *nic_cfg, struct spnic_io_queue *rq, - u16 q_id, u32 rq_depth, u16 rq_msix_idx) -{ - int err; - - rq->wqe_type = rq_wqe_type; - rq->q_id = q_id; - rq->msix_entry_idx = rq_msix_idx; - - err = sphw_wq_create(nic_cfg->hwdev, &rq->wq, rq_depth, - (u16)BIT(SPNIC_RQ_WQEBB_SHIFT + rq_wqe_type)); - if (err) { - sdk_err(nic_cfg->dev_hdl, "Failed to create rx queue(%u) wq\n", - q_id); - return err; - } - - rq->rx.pi_virt_addr = dma_alloc_coherent(nic_cfg->dev_hdl, PAGE_SIZE, - &rq->rx.pi_dma_addr, GFP_KERNEL); - if (!rq->rx.pi_virt_addr) { - sphw_wq_destroy(&rq->wq); - nic_err(nic_cfg->dev_hdl, "Failed to allocate rq pi virt addr\n"); - return -ENOMEM; - } - - return 0; -} - -void spnic_destroy_rq(struct spnic_nic_cfg *nic_cfg, struct spnic_io_queue *rq) -{ - dma_free_coherent(nic_cfg->dev_hdl, PAGE_SIZE, rq->rx.pi_virt_addr, - rq->rx.pi_dma_addr); - - sphw_wq_destroy(&rq->wq); -} - -static int create_qp(struct spnic_nic_cfg *nic_cfg, struct spnic_io_queue *sq, - struct spnic_io_queue *rq, u16 q_id, u32 sq_depth, - u32 rq_depth, u16 qp_msix_idx) -{ - int err; - - err = spnic_create_sq(nic_cfg, sq, q_id, sq_depth, qp_msix_idx); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to create sq, qid: %u\n", - q_id); - return err; - } - - err = spnic_create_rq(nic_cfg, rq, q_id, rq_depth, qp_msix_idx); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to create rq, qid: %u\n", - q_id); - goto create_rq_err; - } - - return 0; - -create_rq_err: - spnic_destroy_sq(nic_cfg->hwdev, sq); - - return err; -} - -void destroy_qp(struct spnic_nic_cfg *nic_cfg, struct spnic_io_queue *sq, - struct spnic_io_queue *rq) -{ - spnic_destroy_sq(nic_cfg, sq); - spnic_destroy_rq(nic_cfg, rq); -} - -/* try to alloc the expect number of doorbell, and return the actual number - * of doorbell. - */ -static int spnic_doorbell_change(struct spnic_nic_cfg *nic_cfg, u16 dst_num_db) -{ - void __iomem *db_addr = NULL; - u16 cur_db_num = nic_cfg->allocated_num_db; - u16 db_num_gap, idx, i, cur_db_alloc; - int err; - - if (dst_num_db > nic_cfg->allocated_num_db) { - db_num_gap = dst_num_db - nic_cfg->allocated_num_db; - for (idx = 0; idx < db_num_gap; idx++) { - /* we don't use direct wqe for sq */ - err = sphw_alloc_db_addr(nic_cfg->hwdev, &db_addr, NULL); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to alloc sq doorbell addr\n"); - goto alloc_db_err; - } - nic_cfg->db_addr[cur_db_num + idx] = db_addr; - } - - nic_cfg->allocated_num_db = dst_num_db; - } else if (dst_num_db < nic_cfg->allocated_num_db) { - db_num_gap = nic_cfg->allocated_num_db - dst_num_db; - for (idx = 0; idx < db_num_gap; idx++) { - cur_db_alloc = (cur_db_num - idx) - 1; - sphw_free_db_addr(nic_cfg->hwdev, nic_cfg->db_addr[cur_db_alloc], NULL); - nic_cfg->db_addr[cur_db_alloc] = NULL; - } - - nic_cfg->allocated_num_db = dst_num_db; - } - - return 0; - -alloc_db_err: - for (i = 0; i < idx; i++) { - sphw_free_db_addr(nic_cfg->hwdev, nic_cfg->db_addr[cur_db_num + i], NULL); - nic_cfg->db_addr[cur_db_num + i] = NULL; - } - - return -EFAULT; -} - -int spnic_init_nicio_res(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) { - pr_err("Failed to get nic service adapter\n"); - return -EFAULT; - } - - nic_cfg->max_qps = sphw_func_max_qnum(hwdev); - - nic_cfg->allocated_num_db = 0; - nic_cfg->db_addr = kcalloc(TOTAL_DB_NUM(nic_cfg->max_qps), - sizeof(*nic_cfg->db_addr), GFP_KERNEL); - if (!nic_cfg->db_addr) { - nic_err(nic_cfg->dev_hdl, "Failed to alloc db addr array\n"); - return -ENOMEM; - } - - nic_cfg->ci_vaddr_base = - dma_alloc_coherent(nic_cfg->dev_hdl, CI_TABLE_SIZE(nic_cfg->max_qps, PAGE_SIZE), - &nic_cfg->ci_dma_base, GFP_KERNEL); - if (!nic_cfg->ci_vaddr_base) { - kfree(nic_cfg->db_addr); - nic_err(nic_cfg->dev_hdl, "Failed to allocate ci area\n"); - return -ENOMEM; - } - - return 0; -} - -void spnic_deinit_nicio_res(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) { - pr_err("Failed to get nic service adapter\n"); - return; - } - - dma_free_coherent(nic_cfg->dev_hdl, CI_TABLE_SIZE(nic_cfg->max_qps, PAGE_SIZE), - nic_cfg->ci_vaddr_base, nic_cfg->ci_dma_base); - /* free all doorbell */ - spnic_doorbell_change(nic_cfg, 0); - kfree(nic_cfg->db_addr); -} - -int spnic_alloc_qps(void *hwdev, struct irq_info *qps_msix_arry, - struct spnic_dyna_qp_params *qp_params) -{ - struct spnic_io_queue *sqs = NULL; - struct spnic_io_queue *rqs = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - u16 q_id, i, cur_allocated_db, num_qps; - int err; - - if (!hwdev || !qps_msix_arry || !qp_params) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) { - pr_err("Failed to get nic service adapter\n"); - return -EFAULT; - } - - if (qp_params->num_qps > nic_cfg->max_qps) - return -EINVAL; - - num_qps = qp_params->num_qps; - - cur_allocated_db = nic_cfg->allocated_num_db; - if (cur_allocated_db < TOTAL_DB_NUM(num_qps)) { - err = spnic_doorbell_change(nic_cfg, TOTAL_DB_NUM(num_qps)); - if (err) - return err; - } - - sqs = kcalloc(num_qps, sizeof(*sqs), GFP_KERNEL); - if (!sqs) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate sq\n"); - err = -ENOMEM; - goto alloc_sqs_err; - } - - rqs = kcalloc(num_qps, sizeof(*rqs), GFP_KERNEL); - if (!rqs) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate rq\n"); - err = -ENOMEM; - goto alloc_rqs_err; - } - - for (q_id = 0; q_id < num_qps; q_id++) { - err = create_qp(nic_cfg, &sqs[q_id], &rqs[q_id], q_id, - qp_params->sq_depth, qp_params->rq_depth, - qps_msix_arry[q_id].msix_entry_idx); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate qp %u, err: %d\n", - q_id, err); - goto create_qp_err; - } - } - - qp_params->sqs = sqs; - qp_params->rqs = rqs; - - return 0; - -create_qp_err: - for (i = 0; i < q_id; i++) - destroy_qp(nic_cfg, &sqs[i], &rqs[i]); - - kfree(rqs); - -alloc_rqs_err: - kfree(sqs); - -alloc_sqs_err: - /* Only release the newly added doorbell resource, - * the old resource is still in use - */ - spnic_doorbell_change(nic_cfg, cur_allocated_db); - - return err; -} - -void spnic_free_qps(void *hwdev, struct spnic_dyna_qp_params *qp_params) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - u16 q_id; - - if (!hwdev || !qp_params) - return; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) { - pr_err("Failed to get nic service adapter\n"); - return; - } - - for (q_id = 0; q_id < qp_params->num_qps; q_id++) - destroy_qp(nic_cfg, &qp_params->sqs[q_id], - &qp_params->rqs[q_id]); - - kfree(qp_params->sqs); - kfree(qp_params->rqs); -} - -void init_qps_info(struct spnic_nic_cfg *nic_cfg, struct spnic_dyna_qp_params *qp_params) -{ - struct spnic_io_queue *sqs = qp_params->sqs; - struct spnic_io_queue *rqs = qp_params->rqs; - u16 q_id; - - nic_cfg->num_qps = qp_params->num_qps; - nic_cfg->sq = qp_params->sqs; - nic_cfg->rq = qp_params->rqs; - for (q_id = 0; q_id < nic_cfg->num_qps; q_id++) { - sqs[q_id].tx.cons_idx_addr = SPNIC_CI_VADDR(nic_cfg->ci_vaddr_base, q_id); - /* clear ci value */ - *(u16 *)sqs[q_id].tx.cons_idx_addr = 0; - sqs[q_id].db_addr = nic_cfg->db_addr[q_id]; - - /* The first num_qps doorbell is used by sq */ - rqs[q_id].db_addr = nic_cfg->db_addr[nic_cfg->num_qps + q_id]; - } -} - -int spnic_init_qps(void *hwdev, struct spnic_dyna_qp_params *qp_params) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev || !qp_params) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) { - pr_err("Failed to get nic service adapter\n"); - return -EFAULT; - } - - if (nic_cfg->allocated_num_db > TOTAL_DB_NUM(qp_params->num_qps)) - spnic_doorbell_change(nic_cfg, TOTAL_DB_NUM(qp_params->num_qps)); - - init_qps_info(nic_cfg, qp_params); - - return spnic_init_qp_ctxts(hwdev); -} - -void spnic_deinit_qps(void *hwdev, struct spnic_dyna_qp_params *qp_params) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev || !qp_params) - return; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) { - pr_err("Failed to get nic service adapter\n"); - return; - } - - qp_params->sqs = nic_cfg->sq; - qp_params->rqs = nic_cfg->rq; - qp_params->num_qps = nic_cfg->num_qps; - - spnic_free_qp_ctxts(hwdev); -} - -int spnic_create_qps(void *hwdev, u16 num_qp, u32 sq_depth, u32 rq_depth, - struct irq_info *qps_msix_arry) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_dyna_qp_params qp_params = {0}; - int err; - - if (!hwdev || !qps_msix_arry) - return -EFAULT; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) { - pr_err("Failed to get nic service adapter\n"); - return -EFAULT; - } - - err = spnic_init_nicio_res(hwdev); - if (err) - return err; - - qp_params.num_qps = num_qp; - qp_params.sq_depth = sq_depth; - qp_params.rq_depth = rq_depth; - err = spnic_alloc_qps(hwdev, qps_msix_arry, &qp_params); - if (err) { - spnic_deinit_nicio_res(hwdev); - nic_err(nic_cfg->dev_hdl, "Failed to allocate qps, err: %d\n", err); - return err; - } - - init_qps_info(nic_cfg, &qp_params); - - return 0; -} - -void spnic_destroy_qps(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_dyna_qp_params qp_params = {0}; - - if (!hwdev) - return; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) - return; - - spnic_deinit_qps(hwdev, &qp_params); - spnic_free_qps(hwdev, &qp_params); - spnic_deinit_nicio_res(hwdev); -} - -void *spnic_get_nic_queue(void *hwdev, u16 q_id, enum spnic_queue_type q_type) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev || q_type >= SPNIC_MAX_QUEUE_TYPE) - return NULL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) - return NULL; - - return ((q_type == SPNIC_SQ) ? &nic_cfg->sq[q_id] : &nic_cfg->rq[q_id]); -} - -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; - - sphw_cpu_to_be32(qp_ctxt_hdr, sizeof(*qp_ctxt_hdr)); -} - -void spnic_sq_prepare_ctxt(struct spnic_io_queue *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 = spnic_get_sq_local_ci(sq); - pi_start = spnic_get_sq_local_pi(sq); - - wq_page_addr = sphw_wq_get_first_wqe_page_addr(&sq->wq); - - 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); - - wq_block_pfn = WQ_BLOCK_PFN(sq->wq.wq_block_paddr); - 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; - - /* TO DO */ - sq_ctxt->pkt_drop_thd = - SQ_CTXT_PKT_DROP_THD_SET(tx_drop_thd_on, THD_ON) | - SQ_CTXT_PKT_DROP_THD_SET(tx_drop_thd_off, THD_OFF); - - sq_ctxt->global_sq_id = - SQ_CTXT_GLOBAL_QUEUE_ID_SET(sq_id, GLOBAL_SQ_ID); - - /* enable 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; - - sphw_cpu_to_be32(sq_ctxt, sizeof(*sq_ctxt)); -} - -void spnic_rq_prepare_ctxt(struct spnic_io_queue *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->wqe_type; - - /* RQ depth is in unit of 8Bytes */ - ci_start = (u16)((u32)spnic_get_rq_local_ci(rq) << wqe_type); - pi_start = (u16)((u32)spnic_get_rq_local_pi(rq) << wqe_type); - - wq_page_addr = sphw_wq_get_first_wqe_page_addr(&rq->wq); - - 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); - - wq_block_pfn = WQ_BLOCK_PFN(rq->wq.wq_block_paddr); - 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); - - rq_ctxt->ceq_attr = RQ_CTXT_CEQ_ATTR_SET(0, EN) | - RQ_CTXT_CEQ_ATTR_SET(rq->msix_entry_idx, INTR); - - 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: - pr_err("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->rx.pi_dma_addr); - rq_ctxt->pi_paddr_lo = lower_32_bits(rq->rx.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; - - sphw_cpu_to_be32(rq_ctxt, sizeof(*rq_ctxt)); -} - -static int init_sq_ctxts(struct spnic_nic_cfg *nic_cfg) -{ - struct spnic_sq_ctxt_block *sq_ctxt_block = NULL; - struct spnic_sq_ctxt *sq_ctxt = NULL; - struct sphw_cmd_buf *cmd_buf = NULL; - struct spnic_io_queue *sq = NULL; - u64 out_param = 0; - u16 q_id, curr_id, max_ctxts, i; - int err = 0; - - cmd_buf = sphw_alloc_cmd_buf(nic_cfg->hwdev); - if (!cmd_buf) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate cmd buf\n"); - return -ENOMEM; - } - - q_id = 0; - while (q_id < nic_cfg->num_qps) { - sq_ctxt_block = cmd_buf->buf; - sq_ctxt = sq_ctxt_block->sq_ctxt; - - max_ctxts = (nic_cfg->num_qps - q_id) > SPNIC_Q_CTXT_MAX ? - SPNIC_Q_CTXT_MAX : (nic_cfg->num_qps - 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_cfg->sq[curr_id]; - - spnic_sq_prepare_ctxt(sq, curr_id, &sq_ctxt[i]); - } - - cmd_buf->size = SQ_CTXT_SIZE(max_ctxts); - - err = sphw_cmdq_direct_resp(nic_cfg->hwdev, SPHW_MOD_L2NIC, - SPNIC_UCODE_CMD_MODIFY_QUEUE_CTX, - cmd_buf, &out_param, 0, SPHW_CHANNEL_NIC); - if (err || out_param != 0) { - nic_err(nic_cfg->dev_hdl, "Failed to set SQ ctxts, err: %d, out_param: 0x%llx\n", - err, out_param); - - err = -EFAULT; - break; - } - - q_id += max_ctxts; - } - - sphw_free_cmd_buf(nic_cfg->hwdev, cmd_buf); - - return err; -} - -static int init_rq_ctxts(struct spnic_nic_cfg *nic_cfg) -{ - struct spnic_rq_ctxt_block *rq_ctxt_block = NULL; - struct spnic_rq_ctxt *rq_ctxt = NULL; - struct sphw_cmd_buf *cmd_buf = NULL; - struct spnic_io_queue *rq = NULL; - u64 out_param = 0; - u16 q_id, curr_id, max_ctxts, i; - int err = 0; - - cmd_buf = sphw_alloc_cmd_buf(nic_cfg->hwdev); - if (!cmd_buf) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate cmd buf\n"); - return -ENOMEM; - } - - q_id = 0; - while (q_id < nic_cfg->num_qps) { - rq_ctxt_block = cmd_buf->buf; - rq_ctxt = rq_ctxt_block->rq_ctxt; - - max_ctxts = (nic_cfg->num_qps - q_id) > SPNIC_Q_CTXT_MAX ? - SPNIC_Q_CTXT_MAX : (nic_cfg->num_qps - 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_cfg->rq[curr_id]; - - spnic_rq_prepare_ctxt(rq, &rq_ctxt[i]); - } - - cmd_buf->size = RQ_CTXT_SIZE(max_ctxts); - - err = sphw_cmdq_direct_resp(nic_cfg->hwdev, SPHW_MOD_L2NIC, - SPNIC_UCODE_CMD_MODIFY_QUEUE_CTX, - cmd_buf, &out_param, 0, SPHW_CHANNEL_NIC); - - if (err || out_param != 0) { - nic_err(nic_cfg->dev_hdl, "Failed to set RQ ctxts, err: %d, out_param: 0x%llx\n", - err, out_param); - - err = -EFAULT; - break; - } - - q_id += max_ctxts; - } - - sphw_free_cmd_buf(nic_cfg->hwdev, cmd_buf); - - return err; -} - -static int init_qp_ctxts(struct spnic_nic_cfg *nic_cfg) -{ - int err; - - err = init_sq_ctxts(nic_cfg); - if (err) - return err; - - err = init_rq_ctxts(nic_cfg); - if (err) - return err; - - return 0; -} - -static int clean_queue_offload_ctxt(struct spnic_nic_cfg *nic_cfg, - enum spnic_qp_ctxt_type ctxt_type) -{ - struct spnic_clean_queue_ctxt *ctxt_block = NULL; - struct sphw_cmd_buf *cmd_buf = NULL; - u64 out_param = 0; - int err; - - cmd_buf = sphw_alloc_cmd_buf(nic_cfg->hwdev); - if (!cmd_buf) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate cmd buf\n"); - return -ENOMEM; - } - - ctxt_block = cmd_buf->buf; - ctxt_block->cmdq_hdr.num_queues = nic_cfg->max_qps; - ctxt_block->cmdq_hdr.queue_type = ctxt_type; - ctxt_block->cmdq_hdr.start_qid = 0; - - sphw_cpu_to_be32(ctxt_block, sizeof(*ctxt_block)); - - cmd_buf->size = sizeof(*ctxt_block); - - err = sphw_cmdq_direct_resp(nic_cfg->hwdev, SPHW_MOD_L2NIC, - SPNIC_UCODE_CMD_CLEAN_QUEUE_CONTEXT, - cmd_buf, &out_param, 0, SPHW_CHANNEL_NIC); - - if ((err) || (out_param)) { - nic_err(nic_cfg->dev_hdl, "Failed to clean queue offload ctxts, err: %d,out_param: 0x%llx\n", - err, out_param); - - err = -EFAULT; - } - - sphw_free_cmd_buf(nic_cfg->hwdev, cmd_buf); - - return err; -} - -static int clean_qp_offload_ctxt(struct spnic_nic_cfg *nic_cfg) -{ - /* clean LRO/TSO context space */ - return (clean_queue_offload_ctxt(nic_cfg, SPNIC_QP_CTXT_TYPE_SQ) || - clean_queue_offload_ctxt(nic_cfg, SPNIC_QP_CTXT_TYPE_RQ)); -} - -/* init qps ctxt and set sq ci attr and arm all sq*/ -int spnic_init_qp_ctxts(void *hwdev) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - struct spnic_sq_attr sq_attr; - u32 rq_depth; - u16 q_id; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - if (!nic_cfg) - return -EFAULT; - - err = init_qp_ctxts(nic_cfg); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to init QP ctxts\n"); - return err; - } - - /* clean LRO/TSO context space */ - err = clean_qp_offload_ctxt(nic_cfg); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to clean qp offload ctxts\n"); - return err; - } - - rq_depth = nic_cfg->rq[0].wq.q_depth << nic_cfg->rq[0].wqe_type; - - err = sphw_set_root_ctxt(hwdev, rq_depth, nic_cfg->sq[0].wq.q_depth, - nic_cfg->rx_buff_len, SPHW_CHANNEL_NIC); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to set root context\n"); - return err; - } - - for (q_id = 0; q_id < nic_cfg->num_qps; q_id++) { - sq_attr.ci_dma_base = SPNIC_CI_PADDR(nic_cfg->ci_dma_base, q_id) >> 2; - sq_attr.pending_limit = tx_pending_limit; - sq_attr.coalescing_time = tx_coalescing_time; - sq_attr.intr_en = 1; - sq_attr.intr_idx = nic_cfg->sq[q_id].msix_entry_idx; - sq_attr.l2nic_sqn = q_id; - sq_attr.dma_attr_off = 0; - err = spnic_set_ci_table(hwdev, &sq_attr); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to set ci table\n"); - goto set_cons_idx_table_err; - } - } - - return 0; - -set_cons_idx_table_err: - sphw_clean_root_ctxt(hwdev, SPHW_CHANNEL_NIC); - - return err; -} - -void spnic_free_qp_ctxts(void *hwdev) -{ - if (!hwdev) - return; - - sphw_clean_root_ctxt(hwdev, SPHW_CHANNEL_NIC); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_io.h b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_io.h deleted file mode 100644 index e237ba33d82d..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_io.h +++ /dev/null @@ -1,305 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_NIC_IO_H -#define SPNIC_NIC_IO_H - -#include "sphw_crm.h" -#include "sphw_common.h" -#include "sphw_wq.h" - -#define SPNIC_MAX_TX_QUEUE_DEPTH 65536 -#define SPNIC_MAX_RX_QUEUE_DEPTH 16384 - -#define SPNIC_MIN_QUEUE_DEPTH 128 - -#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 - -enum spnic_rq_wqe_type { - SPNIC_COMPACT_RQ_WQE, - SPNIC_NORMAL_RQ_WQE, - SPNIC_EXTEND_RQ_WQE, -}; - -struct spnic_io_queue { - struct sphw_wq wq; - union { - u8 wqe_type; /* for rq */ - u8 owner; /* for sq */ - }; - - u16 q_id; - u16 msix_entry_idx; - - u8 __iomem *db_addr; - - union { - struct { - void *cons_idx_addr; - } tx; - - struct { - u16 *pi_virt_addr; - dma_addr_t pi_dma_addr; - } rx; - }; -} ____cacheline_aligned; - -struct spnic_nic_db { - u32 db_info; - u32 pi_hi; -}; - -/* * - * @brief spnic_get_sq_free_wqebbs - get send queue free wqebb - * @param sq: send queue - * @retval : number of free wqebb - */ -static inline u16 spnic_get_sq_free_wqebbs(struct spnic_io_queue *sq) -{ - return sphw_wq_free_wqebbs(&sq->wq); -} - -/* * - * @brief spnic_update_sq_local_ci - update send queue local consumer index - * @param sq: send queue - * @param wqe_cnt: number of wqebb - */ -static inline void spnic_update_sq_local_ci(struct spnic_io_queue *sq, u16 wqebb_cnt) -{ - sphw_wq_put_wqebbs(&sq->wq, wqebb_cnt); -} - -/* * - * @brief spnic_get_sq_local_ci - get send queue local consumer index - * @param sq: send queue - * @retval : local consumer index - */ -static inline u16 spnic_get_sq_local_ci(struct spnic_io_queue *sq) -{ - return WQ_MASK_IDX(&sq->wq, sq->wq.cons_idx); -} - -/* * - * @brief spnic_get_sq_local_pi - get send queue local producer index - * @param sq: send queue - * @retval : local producer index - */ -static inline u16 spnic_get_sq_local_pi(struct spnic_io_queue *sq) -{ - return WQ_MASK_IDX(&sq->wq, sq->wq.prod_idx); -} - -/* * - * @brief spnic_get_sq_hw_ci - get send queue hardware consumer index - * @param sq: send queue - * @retval : hardware consumer index - */ -static inline u16 spnic_get_sq_hw_ci(struct spnic_io_queue *sq) -{ - return WQ_MASK_IDX(&sq->wq, *(u16 *)sq->tx.cons_idx_addr); -} - -/* * - * @brief spnic_get_sq_one_wqebb - get send queue wqe with single wqebb - * @param sq: send queue - * @param pi: return current pi - * @retval : wqe base address - */ -static inline void *spnic_get_sq_one_wqebb(struct spnic_io_queue *sq, u16 *pi) -{ - return sphw_wq_get_one_wqebb(&sq->wq, pi); -} - -/* * - * @brief spnic_get_sq_multi_wqebb - get send queue wqe with multiple wqebbs - * @param sq: send queue - * @param wqebb_cnt: wqebb counter - * @param pi: return current pi - * @param second_part_wqebbs_addr: second part wqebbs base address - * @param first_part_wqebbs_num: number wqebbs of first part - * @retval : first part wqebbs base address - */ -static inline void *spnic_get_sq_multi_wqebbs(struct spnic_io_queue *sq, u16 wqebb_cnt, u16 *pi, - void **second_part_wqebbs_addr, - u16 *first_part_wqebbs_num) -{ - return sphw_wq_get_multi_wqebbs(&sq->wq, wqebb_cnt, pi, second_part_wqebbs_addr, - first_part_wqebbs_num); -} - -/* * - * @brief spnic_get_and_update_sq_owner - get and update send queue owner bit - * @param sq: send queue - * @param curr_pi: current pi - * @param wqebb_cnt: wqebb counter - * @retval : owner bit - */ -static inline u16 spnic_get_and_update_sq_owner(struct spnic_io_queue *sq, - u16 curr_pi, u16 wqebb_cnt) -{ - u16 owner = sq->owner; - - if (unlikely(curr_pi + wqebb_cnt >= sq->wq.q_depth)) - sq->owner = !sq->owner; - - return owner; -} - -/* * - * @brief spnic_get_sq_wqe_with_owner - get send queue wqe with owner - * @param sq: send queue - * @param wqebb_cnt: wqebb counter - * @param pi: return current pi - * @param owner: return owner bit - * @param second_part_wqebbs_addr: second part wqebbs base address - * @param first_part_wqebbs_num: number wqebbs of first part - * @retval : first part wqebbs base address - */ -static inline void *spnic_get_sq_wqe_with_owner(struct spnic_io_queue *sq, - u16 wqebb_cnt, u16 *pi, u16 *owner, - void **second_part_wqebbs_addr, - u16 *first_part_wqebbs_num) -{ - void *wqe = sphw_wq_get_multi_wqebbs(&sq->wq, wqebb_cnt, pi, second_part_wqebbs_addr, - first_part_wqebbs_num); - - *owner = sq->owner; - if (unlikely(*pi + wqebb_cnt >= sq->wq.q_depth)) - sq->owner = !sq->owner; - - return wqe; -} - -/* * - * @brief spnic_rollback_sq_wqebbs - rollback send queue wqe - * @param sq: send queue - * @param wqebb_cnt: wqebb counter - * @param owner: owner bit - */ -static inline void spnic_rollback_sq_wqebbs(struct spnic_io_queue *sq, u16 wqebb_cnt, u16 owner) -{ - if (owner != sq->owner) - sq->owner = owner; - sq->wq.prod_idx -= wqebb_cnt; -} - -/* * - * @brief spnic_rq_wqe_addr - get receive queue wqe address by queue index - * @param rq: receive queue - * @param idx: wq index - * @retval: wqe base address - */ -static inline void *spnic_rq_wqe_addr(struct spnic_io_queue *rq, u16 idx) -{ - return sphw_wq_wqebb_addr(&rq->wq, idx); -} - -/* * - * @brief spnic_update_rq_hw_pi - update receive queue hardware pi - * @param rq: receive queue - * @param pi: pi - */ -static inline void spnic_update_rq_hw_pi(struct spnic_io_queue *rq, u16 pi) -{ - *rq->rx.pi_virt_addr = cpu_to_be16((pi & rq->wq.idx_mask) << rq->wqe_type); -} - -/* * - * @brief spnic_update_rq_local_ci - update receive queue local consumer index - * @param sq: receive queue - * @param wqe_cnt: number of wqebb - */ -static inline void spnic_update_rq_local_ci(struct spnic_io_queue *rq, u16 wqebb_cnt) -{ - sphw_wq_put_wqebbs(&rq->wq, wqebb_cnt); -} - -/* * - * @brief spnic_get_rq_local_ci - get receive queue local ci - * @param rq: receive queue - * @retval: receive queue local ci - */ -static inline u16 spnic_get_rq_local_ci(struct spnic_io_queue *rq) -{ - return WQ_MASK_IDX(&rq->wq, rq->wq.cons_idx); -} - -/* * - * @brief spnic_get_rq_local_pi - get receive queue local pi - * @param rq: receive queue - * @retval: receive queue local pi - */ -static inline u16 spnic_get_rq_local_pi(struct spnic_io_queue *rq) -{ - return WQ_MASK_IDX(&rq->wq, rq->wq.prod_idx); -} - -/* ******************** DB INFO ******************** */ -#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_ADDR(queue, pi) ((u64 *)((queue)->db_addr) + DB_PI_LOW(pi)) -#define SRC_TYPE 1 - -/* CFLAG_DATA_PATH */ -#define SQ_CFLAG_DP 0 -#define RQ_CFLAG_DP 1 -/* * - * @brief spnic_write_db - write doorbell - * @param queue: nic io queue - * @param cos: cos index - * @param cflag: 0--sq, 1--rq - * @param pi: product index - */ -static inline void spnic_write_db(struct spnic_io_queue *queue, int cos, u8 cflag, u16 pi) -{ - struct spnic_nic_db db; - - db.db_info = DB_INFO_SET(SRC_TYPE, TYPE) | DB_INFO_SET(cflag, CFLAG) | - DB_INFO_SET(cos, COS) | DB_INFO_SET(queue->q_id, QID); - db.pi_hi = DB_PI_HIGH(pi); - - wmb(); /* Write all before the doorbell */ - - writeq(*((u64 *)&db), DB_ADDR(queue, pi)); -} - -struct spnic_dyna_qp_params { - u16 num_qps; - u32 sq_depth; - u32 rq_depth; - - struct spnic_io_queue *sqs; - struct spnic_io_queue *rqs; -}; - -int spnic_alloc_qps(void *hwdev, struct irq_info *qps_msix_arry, - struct spnic_dyna_qp_params *qp_params); -void spnic_free_qps(void *hwdev, struct spnic_dyna_qp_params *qp_params); -int spnic_init_qps(void *hwdev, struct spnic_dyna_qp_params *qp_params); -void spnic_deinit_qps(void *hwdev, struct spnic_dyna_qp_params *qp_params); -int spnic_init_nicio_res(void *hwdev); -void spnic_deinit_nicio_res(void *hwdev); -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_qp.h b/drivers/net/ethernet/ramaxel/spnic/spnic_nic_qp.h deleted file mode 100644 index a8abdc1734d3..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_nic_qp.h +++ /dev/null @@ -1,416 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_NIC_QP_H -#define SPNIC_NIC_QP_H - -#include "sphw_common.h" - -#define TX_MSS_DEFAULT 0x3E00 -#define TX_MSS_MIN 0x50 - -#define SPNIC_MAX_SQ_SGE 18 - -#define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_SHIFT 0 -#define RQ_CQE_OFFOLAD_TYPE_IP_TYPE_SHIFT 5 -#define RQ_CQE_OFFOLAD_TYPE_ENC_L3_TYPE_SHIFT 7 -#define RQ_CQE_OFFOLAD_TYPE_TUNNEL_PKT_FORMAT_SHIFT 8 -#define RQ_CQE_OFFOLAD_TYPE_PKT_UMBCAST_SHIFT 19 -#define RQ_CQE_OFFOLAD_TYPE_VLAN_EN_SHIFT 21 -#define RQ_CQE_OFFOLAD_TYPE_RSS_TYPE_SHIFT 24 - -#define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_MASK 0x1FU -#define RQ_CQE_OFFOLAD_TYPE_IP_TYPE_MASK 0x3U -#define RQ_CQE_OFFOLAD_TYPE_ENC_L3_TYPE_MASK 0x1U -#define RQ_CQE_OFFOLAD_TYPE_TUNNEL_PKT_FORMAT_MASK 0xFU -#define RQ_CQE_OFFOLAD_TYPE_PKT_UMBCAST_MASK 0x3U -#define RQ_CQE_OFFOLAD_TYPE_VLAN_EN_MASK 0x1U -#define RQ_CQE_OFFOLAD_TYPE_RSS_TYPE_MASK 0xFFU - -#define RQ_CQE_OFFOLAD_TYPE_GET(val, member) \ - (((val) >> RQ_CQE_OFFOLAD_TYPE_##member##_SHIFT) & \ - RQ_CQE_OFFOLAD_TYPE_##member##_MASK) - -#define SPNIC_GET_RX_PKT_TYPE(offload_type) \ - RQ_CQE_OFFOLAD_TYPE_GET(offload_type, PKT_TYPE) -#define SPNIC_GET_RX_IP_TYPE(offload_type) \ - RQ_CQE_OFFOLAD_TYPE_GET(offload_type, IP_TYPE) -#define SPNIC_GET_RX_ENC_L3_TYPE(offload_type) \ - RQ_CQE_OFFOLAD_TYPE_GET(offload_type, ENC_L3_TYPE) -#define SPNIC_GET_RX_TUNNEL_PKT_FORMAT(offload_type) \ - RQ_CQE_OFFOLAD_TYPE_GET(offload_type, TUNNEL_PKT_FORMAT) - -#define SPNIC_GET_RX_PKT_UMBCAST(offload_type) \ - RQ_CQE_OFFOLAD_TYPE_GET(offload_type, PKT_UMBCAST) - -#define SPNIC_GET_RX_VLAN_OFFLOAD_EN(offload_type) \ - RQ_CQE_OFFOLAD_TYPE_GET(offload_type, VLAN_EN) - -#define SPNIC_GET_RSS_TYPES(offload_type) \ - RQ_CQE_OFFOLAD_TYPE_GET(offload_type, RSS_TYPE) - -#define RQ_CQE_SGE_VLAN_SHIFT 0 -#define RQ_CQE_SGE_LEN_SHIFT 16 - -#define RQ_CQE_SGE_VLAN_MASK 0xFFFFU -#define RQ_CQE_SGE_LEN_MASK 0xFFFFU - -#define RQ_CQE_SGE_GET(val, member) \ - (((val) >> RQ_CQE_SGE_##member##_SHIFT) & RQ_CQE_SGE_##member##_MASK) - -#define SPNIC_GET_RX_VLAN_TAG(vlan_len) RQ_CQE_SGE_GET(vlan_len, VLAN) - -#define SPNIC_GET_RX_PKT_LEN(vlan_len) RQ_CQE_SGE_GET(vlan_len, LEN) - -#define RQ_CQE_STATUS_CSUM_ERR_SHIFT 0 -#define RQ_CQE_STATUS_NUM_LRO_SHIFT 16 -#define RQ_CQE_STATUS_LRO_PUSH_SHIFT 25 -#define RQ_CQE_STATUS_LRO_ENTER_SHIFT 26 -#define RQ_CQE_STATUS_LRO_INTR_SHIFT 27 - -#define RQ_CQE_STATUS_BP_EN_SHIFT 30 -#define RQ_CQE_STATUS_RXDONE_SHIFT 31 -#define RQ_CQE_STATUS_DECRY_PKT_SHIFT 29 -#define RQ_CQE_STATUS_FLUSH_SHIFT 28 - -#define RQ_CQE_STATUS_CSUM_ERR_MASK 0xFFFFU -#define RQ_CQE_STATUS_NUM_LRO_MASK 0xFFU -#define RQ_CQE_STATUS_LRO_PUSH_MASK 0X1U -#define RQ_CQE_STATUS_LRO_ENTER_MASK 0X1U -#define RQ_CQE_STATUS_LRO_INTR_MASK 0X1U -#define RQ_CQE_STATUS_BP_EN_MASK 0X1U -#define RQ_CQE_STATUS_RXDONE_MASK 0x1U -#define RQ_CQE_STATUS_FLUSH_MASK 0x1U -#define RQ_CQE_STATUS_DECRY_PKT_MASK 0x1U - -#define RQ_CQE_STATUS_GET(val, member) \ - (((val) >> RQ_CQE_STATUS_##member##_SHIFT) & \ - RQ_CQE_STATUS_##member##_MASK) - -#define SPNIC_GET_RX_CSUM_ERR(status) RQ_CQE_STATUS_GET(status, CSUM_ERR) - -#define SPNIC_GET_RX_DONE(status) RQ_CQE_STATUS_GET(status, RXDONE) - -#define SPNIC_GET_RX_FLUSH(status) RQ_CQE_STATUS_GET(status, FLUSH) - -#define SPNIC_GET_RX_BP_EN(status) RQ_CQE_STATUS_GET(status, BP_EN) - -#define SPNIC_GET_RX_NUM_LRO(status) RQ_CQE_STATUS_GET(status, NUM_LRO) - -#define SPNIC_RX_IS_DECRY_PKT(status) RQ_CQE_STATUS_GET(status, DECRY_PKT) - -#define RQ_CQE_SUPER_CQE_EN_SHIFT 0 -#define RQ_CQE_PKT_NUM_SHIFT 1 -#define RQ_CQE_PKT_LAST_LEN_SHIFT 6 -#define RQ_CQE_PKT_FIRST_LEN_SHIFT 19 - -#define RQ_CQE_SUPER_CQE_EN_MASK 0x1 -#define RQ_CQE_PKT_NUM_MASK 0x1FU -#define RQ_CQE_PKT_FIRST_LEN_MASK 0x1FFFU -#define RQ_CQE_PKT_LAST_LEN_MASK 0x1FFFU - -#define RQ_CQE_PKT_NUM_GET(val, member) \ - (((val) >> RQ_CQE_PKT_##member##_SHIFT) & RQ_CQE_PKT_##member##_MASK) -#define SPNIC_GET_RQ_CQE_PKT_NUM(pkt_info) RQ_CQE_PKT_NUM_GET(pkt_info, NUM) - -#define RQ_CQE_SUPER_CQE_EN_GET(val, member) \ - (((val) >> RQ_CQE_##member##_SHIFT) & RQ_CQE_##member##_MASK) -#define SPNIC_GET_SUPER_CQE_EN(pkt_info) \ - RQ_CQE_SUPER_CQE_EN_GET(pkt_info, SUPER_CQE_EN) - -#define RQ_CQE_PKT_LEN_GET(val, member) \ - (((val) >> RQ_CQE_PKT_##member##_SHIFT) & RQ_CQE_PKT_##member##_MASK) - -#define RQ_CQE_DECRY_INFO_DECRY_STATUS_SHIFT 8 -#define RQ_CQE_DECRY_INFO_ESP_NEXT_HEAD_SHIFT 0 - -#define RQ_CQE_DECRY_INFO_DECRY_STATUS_MASK 0xFFU -#define RQ_CQE_DECRY_INFO_ESP_NEXT_HEAD_MASK 0xFFU - -#define RQ_CQE_DECRY_INFO_GET(val, member) \ - (((val) >> RQ_CQE_DECRY_INFO_##member##_SHIFT) & \ - RQ_CQE_DECRY_INFO_##member##_MASK) - -#define SPNIC_GET_DECRYPT_STATUS(decry_info) \ - RQ_CQE_DECRY_INFO_GET(decry_info, DECRY_STATUS) - -#define SPNIC_GET_ESP_NEXT_HEAD(decry_info) \ - RQ_CQE_DECRY_INFO_GET(decry_info, ESP_NEXT_HEAD) - -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; -}; - -struct spnic_sge_sect { - struct sphw_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_sq_wqe_desc { - u32 ctrl_len; - u32 queue_info; - u32 hi_addr; - u32 lo_addr; -}; - -/* Engine only pass first 12B TS field directly to uCode through metadata - * vlan_offoad is used for hardware when vlan insert in tx - */ -struct spnic_sq_task { - u32 pkt_info0; - u32 ip_identify; - u32 pkt_info2; /* ipsec used as spi */ - u32 vlan_offload; -}; - -struct spnic_sq_bufdesc { - u32 len; /* 31-bits Length, L2NIC only use length[17:0] */ - u32 rsvd; - u32 hi_addr; - u32 lo_addr; -}; - -struct spnic_sq_compact_wqe { - struct spnic_sq_wqe_desc wqe_desc; -}; - -struct spnic_sq_extend_wqe { - struct spnic_sq_wqe_desc wqe_desc; - struct spnic_sq_task task; - struct spnic_sq_bufdesc buf_desc[0]; -}; - -struct spnic_sq_wqe { - union { - struct spnic_sq_compact_wqe compact_wqe; - struct spnic_sq_extend_wqe extend_wqe; - }; -}; - -/* use section pointer for support non continuous wqe */ -struct spnic_sq_wqe_combo { - struct spnic_sq_wqe_desc *ctrl_bd0; - struct spnic_sq_task *task; - struct spnic_sq_bufdesc *bds_head; - struct spnic_sq_bufdesc *bds_sec2; - u16 first_bds_num; - u32 wqe_type; - u32 task_type; -}; - -/* ************* SQ_CTRL ************** */ -enum sq_wqe_data_format { - SQ_NORMAL_WQE = 0, -}; - -enum sq_wqe_ec_type { - SQ_WQE_COMPACT_TYPE = 0, - SQ_WQE_EXTENDED_TYPE = 1, -}; - -enum sq_wqe_tasksect_len_type { - SQ_WQE_TASKSECT_46BITS = 0, - SQ_WQE_TASKSECT_16BYTES = 1, -}; - -#define SQ_CTRL_BD0_LEN_SHIFT 0 -#define SQ_CTRL_RSVD_SHIFT 18 -#define SQ_CTRL_BUFDESC_NUM_SHIFT 19 -#define SQ_CTRL_TASKSECT_LEN_SHIFT 27 -#define SQ_CTRL_DATA_FORMAT_SHIFT 28 -#define SQ_CTRL_DIRECT_SHIFT 29 -#define SQ_CTRL_EXTENDED_SHIFT 30 -#define SQ_CTRL_OWNER_SHIFT 31 - -#define SQ_CTRL_BD0_LEN_MASK 0x3FFFFU -#define SQ_CTRL_RSVD_MASK 0x1U -#define SQ_CTRL_BUFDESC_NUM_MASK 0xFFU -#define SQ_CTRL_TASKSECT_LEN_MASK 0x1U -#define SQ_CTRL_DATA_FORMAT_MASK 0x1U -#define SQ_CTRL_DIRECT_MASK 0x1U -#define SQ_CTRL_EXTENDED_MASK 0x1U -#define SQ_CTRL_OWNER_MASK 0x1U - -#define SQ_CTRL_SET(val, member) \ - (((u32)(val) & SQ_CTRL_##member##_MASK) << SQ_CTRL_##member##_SHIFT) - -#define SQ_CTRL_GET(val, member) \ - (((val) >> SQ_CTRL_##member##_SHIFT) & SQ_CTRL_##member##_MASK) - -#define SQ_CTRL_CLEAR(val, member) \ - ((val) & (~(SQ_CTRL_##member##_MASK << SQ_CTRL_##member##_SHIFT))) - -#define SQ_CTRL_QUEUE_INFO_PKT_TYPE_SHIFT 0 -#define SQ_CTRL_QUEUE_INFO_PLDOFF_SHIFT 2 -#define SQ_CTRL_QUEUE_INFO_UFO_SHIFT 10 -#define SQ_CTRL_QUEUE_INFO_TSO_SHIFT 11 -#define SQ_CTRL_QUEUE_INFO_TCPUDP_CS_SHIFT 12 -#define SQ_CTRL_QUEUE_INFO_MSS_SHIFT 13 -#define SQ_CTRL_QUEUE_INFO_SCTP_SHIFT 27 -#define SQ_CTRL_QUEUE_INFO_UC_SHIFT 28 -#define SQ_CTRL_QUEUE_INFO_PRI_SHIFT 29 - -#define SQ_CTRL_QUEUE_INFO_PKT_TYPE_MASK 0x3U -#define SQ_CTRL_QUEUE_INFO_PLDOFF_MASK 0xFFU -#define SQ_CTRL_QUEUE_INFO_UFO_MASK 0x1U -#define SQ_CTRL_QUEUE_INFO_TSO_MASK 0x1U -#define SQ_CTRL_QUEUE_INFO_TCPUDP_CS_MASK 0x1U -#define SQ_CTRL_QUEUE_INFO_MSS_MASK 0x3FFFU -#define SQ_CTRL_QUEUE_INFO_SCTP_MASK 0x1U -#define SQ_CTRL_QUEUE_INFO_UC_MASK 0x1U -#define SQ_CTRL_QUEUE_INFO_PRI_MASK 0x7U - -#define SQ_CTRL_QUEUE_INFO_SET(val, member) \ - (((u32)(val) & SQ_CTRL_QUEUE_INFO_##member##_MASK) << \ - SQ_CTRL_QUEUE_INFO_##member##_SHIFT) - -#define SQ_CTRL_QUEUE_INFO_GET(val, member) \ - (((val) >> SQ_CTRL_QUEUE_INFO_##member##_SHIFT) & \ - SQ_CTRL_QUEUE_INFO_##member##_MASK) - -#define SQ_CTRL_QUEUE_INFO_CLEAR(val, member) \ - ((val) & (~(SQ_CTRL_QUEUE_INFO_##member##_MASK << \ - SQ_CTRL_QUEUE_INFO_##member##_SHIFT))) - -#define SQ_TASK_INFO0_TUNNEL_FLAG_SHIFT 19 -#define SQ_TASK_INFO0_ESP_NEXT_PROTO_SHIFT 22 -#define SQ_TASK_INFO0_INNER_L4_EN_SHIFT 24 -#define SQ_TASK_INFO0_INNER_L3_EN_SHIFT 25 -#define SQ_TASK_INFO0_INNER_L4_PSEUDO_SHIFT 26 -#define SQ_TASK_INFO0_OUT_L4_EN_SHIFT 27 -#define SQ_TASK_INFO0_OUT_L3_EN_SHIFT 28 -#define SQ_TASK_INFO0_OUT_L4_PSEUDO_SHIFT 29 -#define SQ_TASK_INFO0_ESP_OFFLOAD_SHIFT 30 -#define SQ_TASK_INFO0_IPSEC_PROTO_SHIFT 31 - -#define SQ_TASK_INFO0_TUNNEL_FLAG_MASK 0x1U -#define SQ_TASK_INFO0_ESP_NEXT_PROTO_MASK 0x3U -#define SQ_TASK_INFO0_INNER_L4_EN_MASK 0x1U -#define SQ_TASK_INFO0_INNER_L3_EN_MASK 0x1U -#define SQ_TASK_INFO0_INNER_L4_PSEUDO_MASK 0x1U -#define SQ_TASK_INFO0_OUT_L4_EN_MASK 0x1U -#define SQ_TASK_INFO0_OUT_L3_EN_MASK 0x1U -#define SQ_TASK_INFO0_OUT_L4_PSEUDO_MASK 0x1U -#define SQ_TASK_INFO0_ESP_OFFLOAD_MASK 0x1U -#define SQ_TASK_INFO0_IPSEC_PROTO_MASK 0x1U - -#define SQ_TASK_INFO0_SET(val, member) \ - (((u32)(val) & SQ_TASK_INFO0_##member##_MASK) << \ - SQ_TASK_INFO0_##member##_SHIFT) -#define SQ_TASK_INFO0_GET(val, member) \ - (((val) >> SQ_TASK_INFO0_##member##_SHIFT) & \ - SQ_TASK_INFO0_##member##_MASK) - -#define SQ_TASK_INFO1_SET(val, member) \ - (((val) & SQ_TASK_INFO1_##member##_MASK) << \ - SQ_TASK_INFO1_##member##_SHIFT) -#define SQ_TASK_INFO1_GET(val, member) \ - (((val) >> SQ_TASK_INFO1_##member##_SHIFT) & \ - SQ_TASK_INFO1_##member##_MASK) - -#define SQ_TASK_INFO3_VLAN_TAG_SHIFT 0 -#define SQ_TASK_INFO3_VLAN_TYPE_SHIFT 16 -#define SQ_TASK_INFO3_VLAN_TAG_VALID_SHIFT 19 - -#define SQ_TASK_INFO3_VLAN_TAG_MASK 0xFFFFU -#define SQ_TASK_INFO3_VLAN_TYPE_MASK 0x7U -#define SQ_TASK_INFO3_VLAN_TAG_VALID_MASK 0x1U - -#define SQ_TASK_INFO3_SET(val, member) \ - (((val) & SQ_TASK_INFO3_##member##_MASK) << \ - SQ_TASK_INFO3_##member##_SHIFT) -#define SQ_TASK_INFO3_GET(val, member) \ - (((val) >> SQ_TASK_INFO3_##member##_SHIFT) & \ - SQ_TASK_INFO3_##member##_MASK) - -static inline u32 spnic_get_pkt_len_for_super_cqe(struct spnic_rq_cqe *cqe, bool last) -{ - u32 pkt_len = cqe->pkt_info; - - if (!last) - return RQ_CQE_PKT_LEN_GET(pkt_len, FIRST_LEN); - else - return RQ_CQE_PKT_LEN_GET(pkt_len, LAST_LEN); -} - -/* * - * spnic_prepare_sq_ctrl - init sq wqe cs - * @nr_descs: total sge_num, include bd0 in cs - * to do : check with zhangxingguo to confirm WQE init - */ -static inline void spnic_prepare_sq_ctrl(struct spnic_sq_wqe_combo *wqe_combo, - u32 queue_info, int nr_descs, u16 owner) -{ - struct spnic_sq_wqe_desc *wqe_desc = wqe_combo->ctrl_bd0; - - if (wqe_combo->wqe_type == SQ_WQE_COMPACT_TYPE) { - wqe_desc->ctrl_len |= - SQ_CTRL_SET(SQ_NORMAL_WQE, DATA_FORMAT) | - SQ_CTRL_SET(wqe_combo->wqe_type, EXTENDED) | - SQ_CTRL_SET(owner, OWNER); - - /* compact wqe queue_info will transfer to ucode */ - wqe_desc->queue_info = 0; - return; - } - - wqe_desc->ctrl_len |= SQ_CTRL_SET(nr_descs, BUFDESC_NUM) | - SQ_CTRL_SET(wqe_combo->task_type, TASKSECT_LEN) | - SQ_CTRL_SET(SQ_NORMAL_WQE, DATA_FORMAT) | - SQ_CTRL_SET(wqe_combo->wqe_type, EXTENDED) | - SQ_CTRL_SET(owner, OWNER); - - wqe_desc->queue_info = queue_info; - wqe_desc->queue_info |= SQ_CTRL_QUEUE_INFO_SET(1U, UC); - - if (!SQ_CTRL_QUEUE_INFO_GET(wqe_desc->queue_info, MSS)) { - wqe_desc->queue_info |= SQ_CTRL_QUEUE_INFO_SET(TX_MSS_DEFAULT, MSS); - } else if (SQ_CTRL_QUEUE_INFO_GET(wqe_desc->queue_info, MSS) < TX_MSS_MIN) { - /* mss should not less than 80 */ - wqe_desc->queue_info = SQ_CTRL_QUEUE_INFO_CLEAR(wqe_desc->queue_info, MSS); - wqe_desc->queue_info |= SQ_CTRL_QUEUE_INFO_SET(TX_MSS_MIN, MSS); - } -} - -/* * - * spnic_set_vlan_tx_offload - set vlan offload info - * @task: wqe task section - * @vlan_tag: vlan tag - * @vlan_type: 0--select TPID0 in IPSU, 1--select TPID0 in IPSU - * 2--select TPID2 in IPSU, 3--select TPID3 in IPSU, 4--select TPID4 in IPSU - */ -static inline void spnic_set_vlan_tx_offload(struct spnic_sq_task *task, u16 vlan_tag, u8 vlan_type) -{ - task->vlan_offload = SQ_TASK_INFO3_SET(vlan_tag, VLAN_TAG) | - SQ_TASK_INFO3_SET(vlan_type, VLAN_TYPE) | - SQ_TASK_INFO3_SET(1U, VLAN_TAG_VALID); -} - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_ntuple.c b/drivers/net/ethernet/ramaxel/spnic/spnic_ntuple.c deleted file mode 100644 index cd92de93a57e..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_ntuple.c +++ /dev/null @@ -1,841 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/device.h> -#include <linux/ethtool.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/types.h> -#include <linux/errno.h> - -#include "sphw_common.h" -#include "sphw_crm.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic_dev.h" - -#define MAX_NUM_OF_ETHTOOL_NTUPLE_RULES BIT(9) -struct spnic_ethtool_rx_flow_rule { - struct list_head list; - struct ethtool_rx_flow_spec flow_spec; -}; - -static void tcam_translate_key_y(u8 *key_y, u8 *src_input, u8 *mask, u8 len) -{ - u8 idx; - - for (idx = 0; idx < len; idx++) - key_y[idx] = src_input[idx] & mask[idx]; -} - -static void tcam_translate_key_x(u8 *key_x, u8 *key_y, u8 *mask, u8 len) -{ - u8 idx; - - for (idx = 0; idx < len; idx++) - key_x[idx] = key_y[idx] ^ mask[idx]; -} - -static void tcam_key_calculate(struct tag_tcam_key *tcam_key, - struct nic_tcam_cfg_rule *fdir_tcam_rule) -{ - tcam_translate_key_y(fdir_tcam_rule->key.y, (u8 *)(&tcam_key->key_info), - (u8 *)(&tcam_key->key_mask), TCAM_FLOW_KEY_SIZE); - tcam_translate_key_x(fdir_tcam_rule->key.x, fdir_tcam_rule->key.y, - (u8 *)(&tcam_key->key_mask), TCAM_FLOW_KEY_SIZE); -} - -#define TCAM_IPV4_TYPE 0 -#define TCAM_IPV6_TYPE 1 - -static int spnic_base_ipv4_parse(struct spnic_nic_dev *nic_dev, struct ethtool_rx_flow_spec *fs, - struct tag_tcam_key *tcam_key) -{ - struct ethtool_tcpip4_spec *mask = &fs->m_u.tcp_ip4_spec; - struct ethtool_tcpip4_spec *val = &fs->h_u.tcp_ip4_spec; - u32 temp; - - switch (mask->ip4src) { - case U32_MAX: - temp = ntohl(val->ip4src); - tcam_key->key_info.sipv4_h = high_16_bits(temp); - tcam_key->key_info.sipv4_l = low_16_bits(temp); - - tcam_key->key_mask.sipv4_h = U16_MAX; - tcam_key->key_mask.sipv4_l = U16_MAX; - break; - case 0: - break; - - default: - nicif_err(nic_dev, drv, nic_dev->netdev, "invalid src_ip mask\n"); - return -EINVAL; - } - - switch (mask->ip4dst) { - case U32_MAX: - temp = ntohl(val->ip4dst); - tcam_key->key_info.dipv4_h = high_16_bits(temp); - tcam_key->key_info.dipv4_l = low_16_bits(temp); - - tcam_key->key_mask.dipv4_h = U16_MAX; - tcam_key->key_mask.dipv4_l = U16_MAX; - break; - case 0: - break; - - default: - nicif_err(nic_dev, drv, nic_dev->netdev, "invalid src_ip mask\n"); - return -EINVAL; - } - - tcam_key->key_info.ip_type = TCAM_IPV4_TYPE; - tcam_key->key_mask.ip_type = TCAM_IP_TYPE_MASK; - - tcam_key->key_info.function_id = sphw_global_func_id(nic_dev->hwdev); - tcam_key->key_mask.function_id = TCAM_FUNC_ID_MASK; - - return 0; -} - -static int spnic_fdir_tcam_ipv4_l4_init(struct spnic_nic_dev *nic_dev, - struct ethtool_rx_flow_spec *fs, - struct tag_tcam_key *tcam_key) -{ - struct ethtool_tcpip4_spec *l4_mask = &fs->m_u.tcp_ip4_spec; - struct ethtool_tcpip4_spec *l4_val = &fs->h_u.tcp_ip4_spec; - int err; - - err = spnic_base_ipv4_parse(nic_dev, fs, tcam_key); - if (err) - return err; - - tcam_key->key_info.dport = ntohs(l4_val->pdst); - tcam_key->key_mask.dport = l4_mask->pdst; - - tcam_key->key_info.sport = ntohs(l4_val->psrc); - tcam_key->key_mask.sport = l4_mask->psrc; - - if (fs->flow_type == TCP_V4_FLOW) - tcam_key->key_info.ip_proto = IPPROTO_TCP; - else - tcam_key->key_info.ip_proto = IPPROTO_UDP; - tcam_key->key_mask.ip_proto = U8_MAX; - - return 0; -} - -static int spnic_fdir_tcam_ipv4_init(struct spnic_nic_dev *nic_dev, - struct ethtool_rx_flow_spec *fs, - struct tag_tcam_key *tcam_key) -{ - struct ethtool_usrip4_spec *l3_mask = &fs->m_u.usr_ip4_spec; - struct ethtool_usrip4_spec *l3_val = &fs->h_u.usr_ip4_spec; - int err; - - err = spnic_base_ipv4_parse(nic_dev, fs, tcam_key); - if (err) - return err; - - tcam_key->key_info.ip_proto = l3_val->proto; - tcam_key->key_mask.ip_proto = l3_mask->proto; - - return 0; -} - -#ifndef UNSUPPORT_NTUPLE_IPV6 -enum ipv6_parse_res { - IPV6_MASK_INVALID, - IPV6_MASK_ALL_MASK, - IPV6_MASK_ALL_ZERO, -}; - -enum ipv6_index { - IPV6_IDX0, - IPV6_IDX1, - IPV6_IDX2, - IPV6_IDX3, -}; - -static int ipv6_mask_parse(u32 *ipv6_mask) -{ - if (ipv6_mask[IPV6_IDX0] == 0 && ipv6_mask[IPV6_IDX1] == 0 && - ipv6_mask[IPV6_IDX2] == 0 && ipv6_mask[IPV6_IDX3] == 0) - return IPV6_MASK_ALL_ZERO; - - if (ipv6_mask[IPV6_IDX0] == U32_MAX && - ipv6_mask[IPV6_IDX1] == U32_MAX && - ipv6_mask[IPV6_IDX2] == U32_MAX && ipv6_mask[IPV6_IDX3] == U32_MAX) - return IPV6_MASK_ALL_MASK; - - return IPV6_MASK_INVALID; -} - -static int spnic_base_ipv6_parse(struct spnic_nic_dev *nic_dev, - struct ethtool_rx_flow_spec *fs, - struct tag_tcam_key *tcam_key) -{ - struct ethtool_tcpip6_spec *mask = &fs->m_u.tcp_ip6_spec; - struct ethtool_tcpip6_spec *val = &fs->h_u.tcp_ip6_spec; - int parse_res; - u32 temp; - - parse_res = ipv6_mask_parse((u32 *)mask->ip6src); - if (parse_res == IPV6_MASK_ALL_MASK) { - temp = ntohl(val->ip6src[IPV6_IDX0]); - tcam_key->key_info_ipv6.sipv6_key0 = high_16_bits(temp); - tcam_key->key_info_ipv6.sipv6_key1 = low_16_bits(temp); - temp = ntohl(val->ip6src[IPV6_IDX1]); - tcam_key->key_info_ipv6.sipv6_key2 = high_16_bits(temp); - tcam_key->key_info_ipv6.sipv6_key3 = low_16_bits(temp); - temp = ntohl(val->ip6src[IPV6_IDX2]); - tcam_key->key_info_ipv6.sipv6_key4 = high_16_bits(temp); - tcam_key->key_info_ipv6.sipv6_key5 = low_16_bits(temp); - temp = ntohl(val->ip6src[IPV6_IDX3]); - tcam_key->key_info_ipv6.sipv6_key6 = high_16_bits(temp); - tcam_key->key_info_ipv6.sipv6_key7 = low_16_bits(temp); - - tcam_key->key_mask_ipv6.sipv6_key0 = U16_MAX; - tcam_key->key_mask_ipv6.sipv6_key1 = U16_MAX; - tcam_key->key_mask_ipv6.sipv6_key2 = U16_MAX; - tcam_key->key_mask_ipv6.sipv6_key3 = U16_MAX; - tcam_key->key_mask_ipv6.sipv6_key4 = U16_MAX; - tcam_key->key_mask_ipv6.sipv6_key5 = U16_MAX; - tcam_key->key_mask_ipv6.sipv6_key6 = U16_MAX; - tcam_key->key_mask_ipv6.sipv6_key7 = U16_MAX; - } else if (parse_res == IPV6_MASK_INVALID) { - nicif_err(nic_dev, drv, nic_dev->netdev, "invalid src_ipv6 mask\n"); - return -EINVAL; - } - - parse_res = ipv6_mask_parse((u32 *)mask->ip6dst); - if (parse_res == IPV6_MASK_ALL_MASK) { - temp = ntohl(val->ip6dst[IPV6_IDX0]); - tcam_key->key_info_ipv6.dipv6_key0 = high_16_bits(temp); - tcam_key->key_info_ipv6.dipv6_key1 = low_16_bits(temp); - temp = ntohl(val->ip6dst[IPV6_IDX1]); - tcam_key->key_info_ipv6.dipv6_key2 = high_16_bits(temp); - tcam_key->key_info_ipv6.dipv6_key3 = low_16_bits(temp); - temp = ntohl(val->ip6dst[IPV6_IDX2]); - tcam_key->key_info_ipv6.dipv6_key4 = high_16_bits(temp); - tcam_key->key_info_ipv6.dipv6_key5 = low_16_bits(temp); - temp = ntohl(val->ip6dst[IPV6_IDX3]); - tcam_key->key_info_ipv6.dipv6_key6 = high_16_bits(temp); - tcam_key->key_info_ipv6.dipv6_key7 = low_16_bits(temp); - - tcam_key->key_mask_ipv6.dipv6_key0 = U16_MAX; - tcam_key->key_mask_ipv6.dipv6_key1 = U16_MAX; - tcam_key->key_mask_ipv6.dipv6_key2 = U16_MAX; - tcam_key->key_mask_ipv6.dipv6_key3 = U16_MAX; - tcam_key->key_mask_ipv6.dipv6_key4 = U16_MAX; - tcam_key->key_mask_ipv6.dipv6_key5 = U16_MAX; - tcam_key->key_mask_ipv6.dipv6_key6 = U16_MAX; - tcam_key->key_mask_ipv6.dipv6_key7 = U16_MAX; - } else if (parse_res == IPV6_MASK_INVALID) { - nicif_err(nic_dev, drv, nic_dev->netdev, "invalid dst_ipv6 mask\n"); - return -EINVAL; - } - - tcam_key->key_info_ipv6.ip_type = TCAM_IPV6_TYPE; - tcam_key->key_mask_ipv6.ip_type = TCAM_IP_TYPE_MASK; - - tcam_key->key_info_ipv6.function_id = sphw_global_func_id(nic_dev->hwdev); - tcam_key->key_mask_ipv6.function_id = TCAM_FUNC_ID_MASK; - - return 0; -} - -static int spnic_fdir_tcam_ipv6_l4_init(struct spnic_nic_dev *nic_dev, - struct ethtool_rx_flow_spec *fs, - struct tag_tcam_key *tcam_key) -{ - struct ethtool_tcpip6_spec *l4_mask = &fs->m_u.tcp_ip6_spec; - struct ethtool_tcpip6_spec *l4_val = &fs->h_u.tcp_ip6_spec; - int err; - - err = spnic_base_ipv6_parse(nic_dev, fs, tcam_key); - if (err) - return err; - - tcam_key->key_info_ipv6.dport = ntohs(l4_val->pdst); - tcam_key->key_mask_ipv6.dport = l4_mask->pdst; - - tcam_key->key_info_ipv6.sport = ntohs(l4_val->psrc); - tcam_key->key_mask_ipv6.sport = l4_mask->psrc; - - if (fs->flow_type == TCP_V6_FLOW) - tcam_key->key_info_ipv6.ip_proto = NEXTHDR_TCP; - else - tcam_key->key_info_ipv6.ip_proto = NEXTHDR_UDP; - tcam_key->key_mask_ipv6.ip_proto = U8_MAX; - - return 0; -} - -static int spnic_fdir_tcam_ipv6_init(struct spnic_nic_dev *nic_dev, - struct ethtool_rx_flow_spec *fs, - struct tag_tcam_key *tcam_key) -{ - struct ethtool_usrip6_spec *l3_mask = &fs->m_u.usr_ip6_spec; - struct ethtool_usrip6_spec *l3_val = &fs->h_u.usr_ip6_spec; - int err; - - err = spnic_base_ipv6_parse(nic_dev, fs, tcam_key); - if (err) - return err; - - tcam_key->key_info_ipv6.ip_proto = l3_val->l4_proto; - tcam_key->key_mask_ipv6.ip_proto = l3_mask->l4_proto; - - return 0; -} -#endif - -static int spnic_fdir_tcam_info_init(struct spnic_nic_dev *nic_dev, - struct ethtool_rx_flow_spec *fs, - struct tag_tcam_key *tcam_key, - struct nic_tcam_cfg_rule *fdir_tcam_rule) -{ - int err; - - switch (fs->flow_type) { - case TCP_V4_FLOW: - case UDP_V4_FLOW: - err = spnic_fdir_tcam_ipv4_l4_init(nic_dev, fs, tcam_key); - if (err) - return err; - break; - case IP_USER_FLOW: - err = spnic_fdir_tcam_ipv4_init(nic_dev, fs, tcam_key); - if (err) - return err; - break; -#ifndef UNSUPPORT_NTUPLE_IPV6 - case TCP_V6_FLOW: - case UDP_V6_FLOW: - err = spnic_fdir_tcam_ipv6_l4_init(nic_dev, fs, tcam_key); - if (err) - return err; - break; - case IPV6_USER_FLOW: - err = spnic_fdir_tcam_ipv6_init(nic_dev, fs, tcam_key); - if (err) - return err; - break; -#endif - default: - return -EOPNOTSUPP; - } - - tcam_key->key_info.tunnel_type = 0; - tcam_key->key_mask.tunnel_type = TCAM_TUNNEL_TYPE_MASK; - - fdir_tcam_rule->data.qid = (u32)fs->ring_cookie; - tcam_key_calculate(tcam_key, fdir_tcam_rule); - - return 0; -} - -void spnic_flush_rx_flow_rule(struct spnic_nic_dev *nic_dev) -{ - struct spnic_tcam_info *tcam_info = &nic_dev->tcam; - struct spnic_ethtool_rx_flow_rule *eth_rule = NULL; - struct spnic_ethtool_rx_flow_rule *eth_rule_tmp = NULL; - struct spnic_tcam_filter *tcam_iter = NULL; - struct spnic_tcam_filter *tcam_iter_tmp = NULL; - struct spnic_tcam_dynamic_block *block = NULL; - struct spnic_tcam_dynamic_block *block_tmp = NULL; - struct list_head *dynamic_list = &tcam_info->tcam_dynamic_info.tcam_dynamic_list; - - if (!list_empty(&tcam_info->tcam_list)) { - list_for_each_entry_safe(tcam_iter, tcam_iter_tmp, &tcam_info->tcam_list, - tcam_filter_list) { - list_del(&tcam_iter->tcam_filter_list); - kfree(tcam_iter); - } - } - if (!list_empty(dynamic_list)) { - list_for_each_entry_safe(block, block_tmp, dynamic_list, block_list) { - list_del(&block->block_list); - kfree(block); - } - } - - if (!list_empty(&nic_dev->rx_flow_rule.rules)) { - list_for_each_entry_safe(eth_rule, eth_rule_tmp, - &nic_dev->rx_flow_rule.rules, list) { - list_del(ð_rule->list); - kfree(eth_rule); - } - } - -#ifndef FPGA_SUPPORT - spnic_flush_tcam_rule(nic_dev->hwdev); - spnic_set_fdir_tcam_rule_filter(nic_dev->hwdev, false); -#endif -} - -static struct spnic_tcam_dynamic_block * -spnic_alloc_dynamic_block_resource(struct spnic_nic_dev *nic_dev, - struct spnic_tcam_info *tcam_info, u16 dynamic_block_id) -{ - struct spnic_tcam_dynamic_block *dynamic_block_ptr = NULL; - - dynamic_block_ptr = kzalloc(sizeof(*dynamic_block_ptr), GFP_KERNEL); - if (!dynamic_block_ptr) { - nicif_err(nic_dev, drv, nic_dev->netdev, "fdir filter dynamic alloc block index %d memory failed\n", - dynamic_block_id); - return NULL; - } - - dynamic_block_ptr->dynamic_block_id = dynamic_block_id; - list_add_tail(&dynamic_block_ptr->block_list, - &tcam_info->tcam_dynamic_info.tcam_dynamic_list); - - tcam_info->tcam_dynamic_info.dynamic_block_cnt++; - - return dynamic_block_ptr; -} - -static void -spnic_free_dynamic_block_resource(struct spnic_tcam_info *tcam_info, - struct spnic_tcam_dynamic_block *block_ptr) -{ - if (!block_ptr) - return; - - list_del(&block_ptr->block_list); - kfree(block_ptr); - - tcam_info->tcam_dynamic_info.dynamic_block_cnt--; -} - -static struct spnic_tcam_dynamic_block * -spnic_dynamic_lookup_tcam_filter(struct spnic_nic_dev *nic_dev, - struct nic_tcam_cfg_rule *fdir_tcam_rule, - struct spnic_tcam_info *tcam_info, - struct spnic_tcam_filter *tcam_filter, u16 *tcam_index) -{ - struct spnic_tcam_dynamic_block *tmp = NULL; - u16 index; - - list_for_each_entry(tmp, &tcam_info->tcam_dynamic_info.tcam_dynamic_list, block_list) - if (tmp->dynamic_index_cnt < SPNIC_TCAM_DYNAMIC_BLOCK_SIZE) - break; - - if (!tmp || tmp->dynamic_index_cnt >= SPNIC_TCAM_DYNAMIC_BLOCK_SIZE) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Fdir filter dynamic lookup for index failed\n"); - return NULL; - } - - for (index = 0; index < SPNIC_TCAM_DYNAMIC_BLOCK_SIZE; index++) - if (tmp->dynamic_index_used[index] == 0) - break; - - if (index == SPNIC_TCAM_DYNAMIC_BLOCK_SIZE) { - nicif_err(nic_dev, drv, nic_dev->netdev, "tcam block 0x%x supports filter rules is full\n", - tmp->dynamic_block_id); - return NULL; - } - - tcam_filter->dynamic_block_id = tmp->dynamic_block_id; - tcam_filter->index = index; - *tcam_index = index; - - fdir_tcam_rule->index = index + - SPNIC_PKT_TCAM_DYNAMIC_INDEX_START(tmp->dynamic_block_id); - - return tmp; -} - -static int spnic_add_tcam_filter(struct spnic_nic_dev *nic_dev, - struct spnic_tcam_filter *tcam_filter, - struct nic_tcam_cfg_rule *fdir_tcam_rule) -{ - struct spnic_tcam_info *tcam_info = &nic_dev->tcam; - struct spnic_tcam_dynamic_block *dynamic_block_ptr = NULL; - struct spnic_tcam_dynamic_block *tmp = NULL; - u16 block_cnt = tcam_info->tcam_dynamic_info.dynamic_block_cnt; - u16 tcam_block_index = 0; - int block_alloc_flag = 0; - u16 index = 0; - int err; - - if (tcam_info->tcam_rule_nums >= - block_cnt * SPNIC_TCAM_DYNAMIC_BLOCK_SIZE) { - if (block_cnt >= (SPNIC_MAX_TCAM_FILTERS / SPNIC_TCAM_DYNAMIC_BLOCK_SIZE)) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Dynamic tcam block is full, alloc failed\n"); - goto failed; - } - - err = spnic_alloc_tcam_block(nic_dev->hwdev, &tcam_block_index); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Fdir filter dynamic tcam alloc block failed\n"); - goto failed; - } - - block_alloc_flag = 1; - - dynamic_block_ptr = - spnic_alloc_dynamic_block_resource(nic_dev, tcam_info, tcam_block_index); - if (!dynamic_block_ptr) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Fdir filter dynamic alloc block memory failed\n"); - goto block_alloc_failed; - } - } - - tmp = spnic_dynamic_lookup_tcam_filter(nic_dev, fdir_tcam_rule, tcam_info, - tcam_filter, &index); - if (!tmp) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Dynamic lookup tcam filter failed\n"); - goto lookup_tcam_index_failed; - } - - err = spnic_add_tcam_rule(nic_dev->hwdev, fdir_tcam_rule); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Fdir_tcam_rule add failed\n"); - goto add_tcam_rules_failed; - } - - nicif_info(nic_dev, drv, nic_dev->netdev, - "Add fdir tcam rule, function_id: 0x%x, tcam_block_id: %d, local_index: %d, global_index: %d, queue: %d, tcam_rule_nums: %d succeed\n", - sphw_global_func_id(nic_dev->hwdev), - tcam_filter->dynamic_block_id, index, fdir_tcam_rule->index, - fdir_tcam_rule->data.qid, tcam_info->tcam_rule_nums + 1); - - if (tcam_info->tcam_rule_nums == 0) { - err = spnic_set_fdir_tcam_rule_filter(nic_dev->hwdev, true); - if (err) - goto enable_failed; - } - - list_add_tail(&tcam_filter->tcam_filter_list, &tcam_info->tcam_list); - - tmp->dynamic_index_used[index] = 1; - tmp->dynamic_index_cnt++; - - tcam_info->tcam_rule_nums++; - - return 0; - -enable_failed: - spnic_del_tcam_rule(nic_dev->hwdev, fdir_tcam_rule->index); - -add_tcam_rules_failed: -lookup_tcam_index_failed: - if (block_alloc_flag == 1) - spnic_free_dynamic_block_resource(tcam_info, dynamic_block_ptr); - -block_alloc_failed: - if (block_alloc_flag == 1) - spnic_free_tcam_block(nic_dev->hwdev, &tcam_block_index); - -failed: - return -EFAULT; -} - -static int spnic_del_tcam_filter(struct spnic_nic_dev *nic_dev, - struct spnic_tcam_filter *tcam_filter) -{ - struct spnic_tcam_info *tcam_info = &nic_dev->tcam; - u16 dynamic_block_id = tcam_filter->dynamic_block_id; - struct spnic_tcam_dynamic_block *tmp = NULL; - u32 index = 0; - int err; - - list_for_each_entry(tmp, &tcam_info->tcam_dynamic_info.tcam_dynamic_list, block_list) { - if (tmp->dynamic_block_id == dynamic_block_id) - break; - } - if (!tmp || tmp->dynamic_block_id != dynamic_block_id) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Fdir filter del dynamic lookup for block failed\n"); - return -EFAULT; - } - - index = SPNIC_PKT_TCAM_DYNAMIC_INDEX_START(tmp->dynamic_block_id) + tcam_filter->index; - - err = spnic_del_tcam_rule(nic_dev->hwdev, index); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "fdir_tcam_rule del failed\n"); - return -EFAULT; - } - - nicif_info(nic_dev, drv, nic_dev->netdev, - "Del fdir_tcam_dynamic_rule function_id: 0x%x, tcam_block_id: %d, local_index: %d, global_index: %d, local_rules_nums: %d, global_rule_nums: %d succeed\n", - sphw_global_func_id(nic_dev->hwdev), dynamic_block_id, - tcam_filter->index, index, tmp->dynamic_index_cnt - 1, - tcam_info->tcam_rule_nums - 1); - - tmp->dynamic_index_used[tcam_filter->index] = 0; - tmp->dynamic_index_cnt--; - tcam_info->tcam_rule_nums--; - if (tmp->dynamic_index_cnt == 0) { - spnic_free_tcam_block(nic_dev->hwdev, &dynamic_block_id); - spnic_free_dynamic_block_resource(tcam_info, tmp); - } - - if (tcam_info->tcam_rule_nums == 0) - spnic_set_fdir_tcam_rule_filter(nic_dev->hwdev, false); - - list_del(&tcam_filter->tcam_filter_list); - kfree(tcam_filter); - - return 0; -} - -static inline struct spnic_tcam_filter * -spnic_tcam_filter_lookup(struct list_head *filter_list, struct tag_tcam_key *key) -{ - struct spnic_tcam_filter *iter; - - list_for_each_entry(iter, filter_list, tcam_filter_list) { - if (memcmp(key, &iter->tcam_key, sizeof(struct tag_tcam_key)) == 0) - return iter; - } - - return NULL; -} - -static void del_ethtool_rule(struct spnic_nic_dev *nic_dev, - struct spnic_ethtool_rx_flow_rule *eth_rule) -{ - list_del(ð_rule->list); - nic_dev->rx_flow_rule.tot_num_rules--; - - kfree(eth_rule); -} - -static int spnic_remove_one_rule(struct spnic_nic_dev *nic_dev, - struct spnic_ethtool_rx_flow_rule *eth_rule) -{ - struct spnic_tcam_info *tcam_info = &nic_dev->tcam; - struct spnic_tcam_filter *tcam_filter; - struct nic_tcam_cfg_rule fdir_tcam_rule; - struct tag_tcam_key tcam_key; - int err; - - memset(&fdir_tcam_rule, 0, sizeof(fdir_tcam_rule)); - memset(&tcam_key, 0, sizeof(tcam_key)); - - err = spnic_fdir_tcam_info_init(nic_dev, ð_rule->flow_spec, &tcam_key, &fdir_tcam_rule); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Init fdir info failed\n"); - return err; - } - - tcam_filter = spnic_tcam_filter_lookup(&tcam_info->tcam_list, &tcam_key); - if (!tcam_filter) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Filter does not exists\n"); - return -EEXIST; - } - - err = spnic_del_tcam_filter(nic_dev, tcam_filter); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Delete tcam filter failed\n"); - return err; - } - - del_ethtool_rule(nic_dev, eth_rule); - - return 0; -} - -static void add_rule_to_list(struct spnic_nic_dev *nic_dev, - struct spnic_ethtool_rx_flow_rule *rule) -{ - struct spnic_ethtool_rx_flow_rule *iter = NULL; - struct list_head *head = &nic_dev->rx_flow_rule.rules; - - list_for_each_entry(iter, &nic_dev->rx_flow_rule.rules, list) { - if (iter->flow_spec.location > rule->flow_spec.location) - break; - head = &iter->list; - } - nic_dev->rx_flow_rule.tot_num_rules++; - list_add(&rule->list, head); -} - -static int spnic_add_one_rule(struct spnic_nic_dev *nic_dev, struct ethtool_rx_flow_spec *fs) -{ - struct nic_tcam_cfg_rule fdir_tcam_rule; - struct tag_tcam_key tcam_key; - struct spnic_ethtool_rx_flow_rule *eth_rule = NULL; - struct spnic_tcam_filter *tcam_filter = NULL; - struct spnic_tcam_info *tcam_info = &nic_dev->tcam; - int err; - - memset(&fdir_tcam_rule, 0, sizeof(fdir_tcam_rule)); - memset(&tcam_key, 0, sizeof(tcam_key)); - err = spnic_fdir_tcam_info_init(nic_dev, fs, &tcam_key, &fdir_tcam_rule); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Init fdir info failed\n"); - return err; - } - - tcam_filter = spnic_tcam_filter_lookup(&tcam_info->tcam_list, &tcam_key); - if (tcam_filter) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Filter exists\n"); - return -EEXIST; - } - - tcam_filter = kzalloc(sizeof(*tcam_filter), GFP_KERNEL); - if (!tcam_filter) - return -ENOMEM; - memcpy(&tcam_filter->tcam_key, &tcam_key, sizeof(struct tag_tcam_key)); - tcam_filter->queue = (u16)fdir_tcam_rule.data.qid; - - err = spnic_add_tcam_filter(nic_dev, tcam_filter, &fdir_tcam_rule); - if (err) - goto add_tcam_filter_fail; - - /* driver save new rule filter */ - eth_rule = kzalloc(sizeof(*eth_rule), GFP_KERNEL); - if (!eth_rule) { - err = -ENOMEM; - goto alloc_eth_rule_fail; - } - - eth_rule->flow_spec = *fs; - add_rule_to_list(nic_dev, eth_rule); - - return 0; - -alloc_eth_rule_fail: - spnic_del_tcam_filter(nic_dev, tcam_filter); -add_tcam_filter_fail: - kfree(tcam_filter); - return err; -} - -static struct spnic_ethtool_rx_flow_rule * -find_ethtool_rule(struct spnic_nic_dev *nic_dev, u32 location) -{ - struct spnic_ethtool_rx_flow_rule *iter = NULL; - - list_for_each_entry(iter, &nic_dev->rx_flow_rule.rules, list) { - if (iter->flow_spec.location == location) - return iter; - } - return NULL; -} - -static int validate_flow(struct spnic_nic_dev *nic_dev, struct ethtool_rx_flow_spec *fs) -{ - if (fs->location >= MAX_NUM_OF_ETHTOOL_NTUPLE_RULES) { - nicif_err(nic_dev, drv, nic_dev->netdev, "loc exceed limit[0,%lu]\n", - MAX_NUM_OF_ETHTOOL_NTUPLE_RULES); - return -EINVAL; - } - - if (fs->ring_cookie >= nic_dev->q_params.num_qps) { - nicif_err(nic_dev, drv, nic_dev->netdev, "action is larger than queue number %u\n", - nic_dev->q_params.num_qps); - return -EINVAL; - } - - switch (fs->flow_type) { - case TCP_V4_FLOW: - case UDP_V4_FLOW: - case IP_USER_FLOW: -#ifndef UNSUPPORT_NTUPLE_IPV6 - case TCP_V6_FLOW: - case UDP_V6_FLOW: - case IPV6_USER_FLOW: -#endif - break; - default: - nicif_err(nic_dev, drv, nic_dev->netdev, "flow type is not supported\n"); - return -EOPNOTSUPP; - } - - return 0; -} - -int spnic_ethtool_flow_replace(struct spnic_nic_dev *nic_dev, struct ethtool_rx_flow_spec *fs) -{ - struct spnic_ethtool_rx_flow_rule *eth_rule = NULL; - struct ethtool_rx_flow_spec flow_spec_temp; - int loc_exit_flag = 0; - int err; - - err = validate_flow(nic_dev, fs); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "flow is not valid %d\n", err); - return err; - } - - eth_rule = find_ethtool_rule(nic_dev, fs->location); - /* when location is same, delete old location rule. */ - if (eth_rule) { - memcpy(&flow_spec_temp, ð_rule->flow_spec, sizeof(struct ethtool_rx_flow_spec)); - err = spnic_remove_one_rule(nic_dev, eth_rule); - if (err) - return err; - - loc_exit_flag = 1; - } - - /* add new rule filter */ - err = spnic_add_one_rule(nic_dev, fs); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Add new rule filter failed\n"); - if (loc_exit_flag) - spnic_add_one_rule(nic_dev, &flow_spec_temp); - - return -ENOENT; - } - - return 0; -} - -int spnic_ethtool_flow_remove(struct spnic_nic_dev *nic_dev, u32 location) -{ - struct spnic_ethtool_rx_flow_rule *eth_rule = NULL; - int err; - - if (location >= MAX_NUM_OF_ETHTOOL_NTUPLE_RULES) - return -ENOSPC; - - eth_rule = find_ethtool_rule(nic_dev, location); - if (!eth_rule) - return -ENOENT; - - err = spnic_remove_one_rule(nic_dev, eth_rule); - - return err; -} - -int spnic_ethtool_get_flow(struct spnic_nic_dev *nic_dev, - struct ethtool_rxnfc *info, u32 location) -{ - struct spnic_ethtool_rx_flow_rule *eth_rule = NULL; - - if (location >= MAX_NUM_OF_ETHTOOL_NTUPLE_RULES) - return -EINVAL; - - list_for_each_entry(eth_rule, &nic_dev->rx_flow_rule.rules, list) { - if (eth_rule->flow_spec.location == location) { - info->fs = eth_rule->flow_spec; - return 0; - } - } - - return -ENOENT; -} - -int spnic_ethtool_get_all_flows(struct spnic_nic_dev *nic_dev, - struct ethtool_rxnfc *info, u32 *rule_locs) -{ - int idx = 0; - struct spnic_ethtool_rx_flow_rule *eth_rule = NULL; - - info->data = MAX_NUM_OF_ETHTOOL_NTUPLE_RULES; - list_for_each_entry(eth_rule, &nic_dev->rx_flow_rule.rules, list) - rule_locs[idx++] = eth_rule->flow_spec.location; - - return info->rule_cnt == idx ? 0 : -ENOENT; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_pci_id_tbl.h b/drivers/net/ethernet/ramaxel/spnic/spnic_pci_id_tbl.h deleted file mode 100644 index 9d32608e6bb7..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_pci_id_tbl.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_PCI_ID_TBL_H -#define SPNIC_PCI_ID_TBL_H - -#define PCI_VENDOR_ID_RAMAXEL 0x1E81 -#define SPNIC_DEV_ID_PF_STD 0x9020 -#define SPNIC_DEV_ID_VF 0x9001 -#define SPNIC_DEV_ID_VF_HV 0x9002 - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_rss.c b/drivers/net/ethernet/ramaxel/spnic/spnic_rss.c deleted file mode 100644 index 956d868df5b5..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_rss.c +++ /dev/null @@ -1,741 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/interrupt.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/device.h> -#include <linux/ethtool.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/dcbnl.h> - -#include "sphw_crm.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic_dev.h" -#include "sphw_hw.h" -#include "spnic_rss.h" - -static u16 num_qps; -module_param(num_qps, ushort, 0444); -MODULE_PARM_DESC(num_qps, "Number of Queue Pairs (default=0)"); - -#define MOD_PARA_VALIDATE_NUM_QPS(nic_dev, num_qps, out_qps) do { \ - if ((num_qps) > (nic_dev)->max_qps) \ - nic_warn(&(nic_dev)->pdev->dev, \ - "Module Parameter %s value %u is out of range, " \ - "Maximum value for the device: %u, using %u\n", \ - #num_qps, num_qps, (nic_dev)->max_qps, \ - (nic_dev)->max_qps); \ - if (!(num_qps) || (num_qps) > (nic_dev)->max_qps) \ - (out_qps) = (nic_dev)->max_qps; \ - else \ - (out_qps) = (num_qps); \ -} while (0) - -static void spnic_fillout_indir_tbl(struct spnic_nic_dev *nic_dev, u8 num_tcs, u32 *indir) -{ - u16 num_rss, tc_group_size; - int i; - - if (num_tcs) - tc_group_size = SPNIC_RSS_INDIR_SIZE / num_tcs; - else - tc_group_size = SPNIC_RSS_INDIR_SIZE; - - num_rss = nic_dev->q_params.num_rss; - for (i = 0; i < SPNIC_RSS_INDIR_SIZE; i++) - indir[i] = (i / tc_group_size) * num_rss + i % num_rss; -} - -int spnic_rss_init(struct spnic_nic_dev *nic_dev) -{ - struct net_device *netdev = nic_dev->netdev; - u8 cos, num_tc = 0; - u8 prio_tc[SPNIC_DCB_UP_MAX] = {0}; - u8 max_cos = nic_dev->hw_dcb_cfg.max_cos; - - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - num_tc = max_cos; - for (cos = 0; cos < SPNIC_DCB_COS_MAX; cos++) { - if (cos < SPNIC_DCB_COS_MAX - max_cos) - prio_tc[cos] = max_cos - 1; - else - prio_tc[cos] = (SPNIC_DCB_COS_MAX - 1) - cos; - } - } else { - num_tc = 0; - } - - return spnic_set_hw_rss_parameters(netdev, 1, num_tc, prio_tc); -} - -void spnic_rss_deinit(struct spnic_nic_dev *nic_dev) -{ - u8 prio_tc[SPNIC_DCB_UP_MAX] = {0}; - - spnic_rss_cfg(nic_dev->hwdev, 0, 0, prio_tc, 1); -} - -void spnic_init_rss_parameters(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - nic_dev->rss_hash_engine = SPNIC_RSS_HASH_ENGINE_TYPE_XOR; - nic_dev->rss_type.tcp_ipv6_ext = 1; - nic_dev->rss_type.ipv6_ext = 1; - nic_dev->rss_type.tcp_ipv6 = 1; - nic_dev->rss_type.ipv6 = 1; - nic_dev->rss_type.tcp_ipv4 = 1; - nic_dev->rss_type.ipv4 = 1; - nic_dev->rss_type.udp_ipv6 = 1; - nic_dev->rss_type.udp_ipv4 = 1; -} - -void spnic_clear_rss_config(struct spnic_nic_dev *nic_dev) -{ - kfree(nic_dev->rss_hkey); - nic_dev->rss_hkey = NULL; - - kfree(nic_dev->rss_indir); - nic_dev->rss_indir = NULL; -} - -void spnic_set_default_rss_indir(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - set_bit(SPNIC_RSS_DEFAULT_INDIR, &nic_dev->flags); -} - -static void spnic_maybe_reconfig_rss_indir(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int i; - - /* if dcb is enabled, user can not config rss indir table */ - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags)) { - nicif_info(nic_dev, drv, netdev, "DCB is enabled, set default rss indir\n"); - goto discard_user_rss_indir; - } - - for (i = 0; i < SPNIC_RSS_INDIR_SIZE; i++) { - if (nic_dev->rss_indir[i] >= nic_dev->q_params.num_qps) - goto discard_user_rss_indir; - } - - return; - -discard_user_rss_indir: - spnic_set_default_rss_indir(netdev); -} - -static void decide_num_qps(struct spnic_nic_dev *nic_dev) -{ - u16 tmp_num_qps = nic_dev->q_params.num_qps; - u16 num_cpus = 0; - int i, node; - - MOD_PARA_VALIDATE_NUM_QPS(nic_dev, num_qps, tmp_num_qps); - - /* To reduce memory footprint in ovs mode. - * VF can't get board info correctly with early pf driver. - */ - /* if ((spnic_get_func_mode(nic_dev->hwdev) == FUNC_MOD_NORMAL_HOST) && - * service_mode == SPNIC_WORK_MODE_OVS && - * sphw_func_type(nic_dev->hwdev) != TYPE_VF) - * MOD_PARA_VALIDATE_NUM_QPS(nic_dev, ovs_num_qps, - * tmp_num_qps); - */ - - for (i = 0; i < (int)num_online_cpus(); i++) { - node = (int)cpu_to_node(i); - if (node == dev_to_node(&nic_dev->pdev->dev)) - num_cpus++; - } - - if (!num_cpus) - num_cpus = (u16)num_online_cpus(); - - nic_dev->q_params.num_qps = min_t(u16, tmp_num_qps, num_cpus); -} - -static void copy_value_to_rss_hkey(struct spnic_nic_dev *nic_dev, const u8 *hkey) -{ - u32 i; - u32 *rss_hkey = (u32 *)nic_dev->rss_hkey; - - memcpy(nic_dev->rss_hkey, hkey, SPNIC_RSS_KEY_SIZE); - - /* make a copy of the key, and convert it to Big Endian */ - for (i = 0; i < SPNIC_RSS_KEY_SIZE / sizeof(u32); i++) - nic_dev->rss_hkey_be[i] = cpu_to_be32(rss_hkey[i]); -} - -int alloc_rss_resource(struct spnic_nic_dev *nic_dev) -{ - u8 default_rss_key[SPNIC_RSS_KEY_SIZE] = { - 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2, - 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0, - 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4, - 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c, - 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa}; - - /* We request double spaces for the hash key, - * the second one holds the key of Big Edian - * format. - */ - nic_dev->rss_hkey = - kzalloc(SPNIC_RSS_KEY_SIZE * SPNIC_RSS_KEY_RSV_NUM, GFP_KERNEL); - if (!nic_dev->rss_hkey) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc memory for rss_hkey\n"); - return -ENOMEM; - } - - /* The second space is for big edian hash key */ - nic_dev->rss_hkey_be = (u32 *)(nic_dev->rss_hkey + SPNIC_RSS_KEY_SIZE); - copy_value_to_rss_hkey(nic_dev, (u8 *)default_rss_key); - - nic_dev->rss_indir = kzalloc(sizeof(u32) * SPNIC_RSS_INDIR_SIZE, GFP_KERNEL); - if (!nic_dev->rss_indir) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc memory for rss_indir\n"); - kfree(nic_dev->rss_hkey); - nic_dev->rss_hkey = NULL; - return -ENOMEM; - } - - set_bit(SPNIC_RSS_DEFAULT_INDIR, &nic_dev->flags); - - return 0; -} - -void spnic_try_to_enable_rss(struct spnic_nic_dev *nic_dev) -{ - u8 prio_tc[SPNIC_DCB_UP_MAX] = {0}; - int err = 0; - - if (!nic_dev) - return; - - nic_dev->max_qps = sphw_func_max_nic_qnum(nic_dev->hwdev); - if (nic_dev->max_qps <= 1 || !SPNIC_SUPPORT_RSS(nic_dev->hwdev)) - goto set_q_params; - - err = alloc_rss_resource(nic_dev); - if (err) { - nic_dev->max_qps = 1; - goto set_q_params; - } - - set_bit(SPNIC_RSS_ENABLE, &nic_dev->flags); - nic_dev->max_qps = sphw_func_max_nic_qnum(nic_dev->hwdev); - - decide_num_qps(nic_dev); - - nic_dev->q_params.rss_limit = nic_dev->q_params.num_qps; - nic_dev->q_params.num_rss = nic_dev->q_params.num_qps; - - spnic_init_rss_parameters(nic_dev->netdev); - err = spnic_set_hw_rss_parameters(nic_dev->netdev, 0, 0, prio_tc); - if (err) { - nic_err(&nic_dev->pdev->dev, "Failed to set hardware rss parameters\n"); - - spnic_clear_rss_config(nic_dev); - nic_dev->max_qps = 1; - goto set_q_params; - } - return; - -set_q_params: - clear_bit(SPNIC_RSS_ENABLE, &nic_dev->flags); - nic_dev->q_params.rss_limit = nic_dev->max_qps; - nic_dev->q_params.num_qps = nic_dev->max_qps; - nic_dev->q_params.num_rss = nic_dev->max_qps; -} - -static int spnic_config_rss_hw_resource(struct spnic_nic_dev *nic_dev, u32 *indir_tbl) -{ - int err; - - err = spnic_rss_set_indir_tbl(nic_dev->hwdev, indir_tbl); - if (err) - return err; - - err = spnic_set_rss_type(nic_dev->hwdev, nic_dev->rss_type); - if (err) - return err; - - return spnic_rss_set_hash_engine(nic_dev->hwdev, nic_dev->rss_hash_engine); -} - -int spnic_set_hw_rss_parameters(struct net_device *netdev, u8 rss_en, u8 num_tc, u8 *prio_tc) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int err; - - /* RSS key */ - err = spnic_rss_set_hash_key(nic_dev->hwdev, nic_dev->rss_hkey); - if (err) - return err; - - spnic_maybe_reconfig_rss_indir(netdev); - - if (test_bit(SPNIC_RSS_DEFAULT_INDIR, &nic_dev->flags)) - spnic_fillout_indir_tbl(nic_dev, num_tc, nic_dev->rss_indir); - - err = spnic_config_rss_hw_resource(nic_dev, nic_dev->rss_indir); - if (err) - return err; - - err = spnic_rss_cfg(nic_dev->hwdev, rss_en, num_tc, prio_tc, nic_dev->q_params.num_qps); - if (err) - return err; - - return 0; -} - -/* for ethtool */ -static int set_l4_rss_hash_ops(struct ethtool_rxnfc *cmd, struct nic_rss_type *rss_type) -{ - u8 rss_l4_en = 0; - - switch (cmd->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - rss_l4_en = 0; - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): - rss_l4_en = 1; - break; - default: - return -EINVAL; - } - - switch (cmd->flow_type) { - case TCP_V4_FLOW: - rss_type->tcp_ipv4 = rss_l4_en; - break; - case TCP_V6_FLOW: - rss_type->tcp_ipv6 = rss_l4_en; - break; - case UDP_V4_FLOW: - rss_type->udp_ipv4 = rss_l4_en; - break; - case UDP_V6_FLOW: - rss_type->udp_ipv6 = rss_l4_en; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int update_rss_hash_opts(struct spnic_nic_dev *nic_dev, struct ethtool_rxnfc *cmd, - struct nic_rss_type *rss_type) -{ - int err; - - switch (cmd->flow_type) { - case TCP_V4_FLOW: - case TCP_V6_FLOW: - case UDP_V4_FLOW: - case UDP_V6_FLOW: - err = set_l4_rss_hash_ops(cmd, rss_type); - if (err) - return err; - - break; - case IPV4_FLOW: - rss_type->ipv4 = 1; - break; - case IPV6_FLOW: - rss_type->ipv6 = 1; - break; - default: - nicif_err(nic_dev, drv, nic_dev->netdev, "Unsupported flow type\n"); - return -EINVAL; - } - - return 0; -} - -static int spnic_set_rss_hash_opts(struct spnic_nic_dev *nic_dev, struct ethtool_rxnfc *cmd) -{ - struct nic_rss_type *rss_type = &nic_dev->rss_type; - int err; - - if (!test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) { - cmd->data = 0; - nicif_err(nic_dev, drv, nic_dev->netdev, - "RSS is disable, not support to set flow-hash\n"); - return -EOPNOTSUPP; - } - - /* RSS does not support anything other than hashing - * to queues on src and dst IPs and ports - */ - if (cmd->data & ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | - RXH_L4_B_2_3)) - return -EINVAL; - - /* We need at least the IP SRC and DEST fields for hashing */ - if (!(cmd->data & RXH_IP_SRC) || !(cmd->data & RXH_IP_DST)) - return -EINVAL; - - err = spnic_get_rss_type(nic_dev->hwdev, rss_type); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to get rss type\n"); - return -EFAULT; - } - - err = update_rss_hash_opts(nic_dev, cmd, rss_type); - if (err) - return err; - - err = spnic_set_rss_type(nic_dev->hwdev, *rss_type); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to set rss type\n"); - return -EFAULT; - } - - nicif_info(nic_dev, drv, nic_dev->netdev, "Set rss hash options success\n"); - - return 0; -} - -static void convert_rss_type(u8 rss_opt, struct ethtool_rxnfc *cmd) -{ - if (rss_opt) - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; -} - -static int spnic_convert_rss_type(struct spnic_nic_dev *nic_dev, struct nic_rss_type *rss_type, - struct ethtool_rxnfc *cmd) -{ - cmd->data = RXH_IP_SRC | RXH_IP_DST; - switch (cmd->flow_type) { - case TCP_V4_FLOW: - convert_rss_type(rss_type->tcp_ipv4, cmd); - break; - case TCP_V6_FLOW: - convert_rss_type(rss_type->tcp_ipv6, cmd); - break; - case UDP_V4_FLOW: - convert_rss_type(rss_type->udp_ipv4, cmd); - break; - case UDP_V6_FLOW: - convert_rss_type(rss_type->udp_ipv6, cmd); - break; - case IPV4_FLOW: - case IPV6_FLOW: - break; - default: - nicif_err(nic_dev, drv, nic_dev->netdev, "Unsupported flow type\n"); - cmd->data = 0; - return -EINVAL; - } - - return 0; -} - -static int spnic_get_rss_hash_opts(struct spnic_nic_dev *nic_dev, struct ethtool_rxnfc *cmd) -{ - struct nic_rss_type rss_type = {0}; - int err; - - cmd->data = 0; - - if (!test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) - return 0; - - err = spnic_get_rss_type(nic_dev->hwdev, &rss_type); - if (err) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to get rss type\n"); - return err; - } - - return spnic_convert_rss_type(nic_dev, &rss_type, cmd); -} - -int spnic_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, u32 *rule_locs) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int err = 0; - - switch (cmd->cmd) { - case ETHTOOL_GRXRINGS: - cmd->data = nic_dev->q_params.num_qps; - break; - case ETHTOOL_GRXCLSRLCNT: - cmd->rule_cnt = nic_dev->rx_flow_rule.tot_num_rules; - break; - case ETHTOOL_GRXCLSRULE: - err = spnic_ethtool_get_flow(nic_dev, cmd, cmd->fs.location); - break; - case ETHTOOL_GRXCLSRLALL: - err = spnic_ethtool_get_all_flows(nic_dev, cmd, rule_locs); - break; - case ETHTOOL_GRXFH: - err = spnic_get_rss_hash_opts(nic_dev, cmd); - break; - default: - err = -EOPNOTSUPP; - break; - } - - return err; -} - -int spnic_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int err = 0; - - switch (cmd->cmd) { - case ETHTOOL_SRXFH: - err = spnic_set_rss_hash_opts(nic_dev, cmd); - break; - case ETHTOOL_SRXCLSRLINS: - err = spnic_ethtool_flow_replace(nic_dev, &cmd->fs); - break; - case ETHTOOL_SRXCLSRLDEL: - err = spnic_ethtool_flow_remove(nic_dev, cmd->fs.location); - break; - default: - err = -EOPNOTSUPP; - break; - } - - return err; -} - -static u16 spnic_max_channels(struct spnic_nic_dev *nic_dev) -{ - u8 tcs = (u8)netdev_get_num_tc(nic_dev->netdev); - - return tcs ? nic_dev->max_qps / tcs : nic_dev->max_qps; -} - -static u16 spnic_curr_channels(struct spnic_nic_dev *nic_dev) -{ - if (netif_running(nic_dev->netdev)) - return nic_dev->q_params.num_rss ? nic_dev->q_params.num_rss : 1; - else - return min_t(u16, spnic_max_channels(nic_dev), - nic_dev->q_params.rss_limit); -} - -void spnic_get_channels(struct net_device *netdev, struct ethtool_channels *channels) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - channels->max_rx = 0; - channels->max_tx = 0; - channels->max_other = 0; - /* report maximum channels */ - channels->max_combined = spnic_max_channels(nic_dev); - channels->rx_count = 0; - channels->tx_count = 0; - channels->other_count = 0; - /* report flow director queues as maximum channels */ - channels->combined_count = spnic_curr_channels(nic_dev); -} - -void spnic_update_num_qps(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u16 num_qps; - u8 tcs; - - /* change num_qps to change counter in ethtool -S */ - tcs = (u8)netdev_get_num_tc(nic_dev->netdev); - nic_dev->q_params.num_tc = tcs; - num_qps = (u16)(nic_dev->q_params.rss_limit * (tcs ? tcs : 1)); - nic_dev->q_params.num_qps = min_t(u16, nic_dev->max_qps, num_qps); -} - -static int spnic_validate_channel_parameter(struct net_device *netdev, - struct ethtool_channels *channels) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u16 max_channel = spnic_max_channels(nic_dev); - unsigned int count = channels->combined_count; - - if (!count) { - nicif_err(nic_dev, drv, netdev, "Unsupported combined_count=0\n"); - return -EINVAL; - } - - if (channels->tx_count || channels->rx_count || channels->other_count) { - nicif_err(nic_dev, drv, netdev, "Setting rx/tx/other count not supported\n"); - return -EINVAL; - } - - if (count > max_channel) { - nicif_err(nic_dev, drv, netdev, "Combined count %u exceed limit %u\n", - count, max_channel); - return -EINVAL; - } - - return 0; -} - -static void change_num_channel_reopen_handler(struct spnic_nic_dev *nic_dev, const void *priv_data) -{ - spnic_set_default_rss_indir(nic_dev->netdev); -} - -int spnic_set_channels(struct net_device *netdev, struct ethtool_channels *channels) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_dyna_txrxq_params q_params = {0}; - unsigned int count = channels->combined_count; - int err; - - if (spnic_validate_channel_parameter(netdev, channels)) - return -EINVAL; - - if (!test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) { - nicif_err(nic_dev, drv, netdev, - "This function don't support RSS, only support 1 queue pair\n"); - return -EOPNOTSUPP; - } - - nicif_info(nic_dev, drv, netdev, "Set max combined queue number from %u to %u\n", - nic_dev->q_params.rss_limit, count); - - if (netif_running(netdev)) { - q_params = nic_dev->q_params; - q_params.rss_limit = (u16)count; - q_params.txqs_res = NULL; - q_params.rxqs_res = NULL; - q_params.irq_cfg = NULL; - - nicif_info(nic_dev, drv, netdev, "Restarting channel\n"); - err = spnic_change_channel_settings(nic_dev, &q_params, - change_num_channel_reopen_handler, NULL); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to change channel settings\n"); - return -EFAULT; - } - } else { - /* Discard user configured rss */ - spnic_set_default_rss_indir(netdev); - nic_dev->q_params.rss_limit = (u16)count; - spnic_update_num_qps(netdev); - } - - return 0; -} - -static int set_rss_rxfh(struct net_device *netdev, const u32 *indir, const u8 *key) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int err; - - if (indir) { - err = spnic_rss_set_indir_tbl(nic_dev->hwdev, indir); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to set rss indir table\n"); - return -EFAULT; - } - clear_bit(SPNIC_RSS_DEFAULT_INDIR, &nic_dev->flags); - - memcpy(nic_dev->rss_indir, indir, - sizeof(u32) * SPNIC_RSS_INDIR_SIZE); - nicif_info(nic_dev, drv, netdev, "Change rss indir success\n"); - } - - if (key) { - err = spnic_rss_set_hash_key(nic_dev->hwdev, key); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to set rss key\n"); - return -EFAULT; - } - - copy_value_to_rss_hkey(nic_dev, key); - nicif_info(nic_dev, drv, netdev, "Change rss key success\n"); - } - - return 0; -} - -u32 spnic_get_rxfh_indir_size(struct net_device *netdev) -{ - return SPNIC_RSS_INDIR_SIZE; -} - -u32 spnic_get_rxfh_key_size(struct net_device *netdev) -{ - return SPNIC_RSS_KEY_SIZE; -} - -int spnic_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int err = 0; - - if (!test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Rss is disable\n"); - return -EOPNOTSUPP; - } - - if (hfunc) - *hfunc = nic_dev->rss_hash_engine ? - ETH_RSS_HASH_TOP : ETH_RSS_HASH_XOR; - - if (indir) { - err = spnic_rss_get_indir_tbl(nic_dev->hwdev, indir); - if (err) - return -EFAULT; - } - - if (key) - memcpy(key, nic_dev->rss_hkey, SPNIC_RSS_KEY_SIZE); - - return err; -} - -int spnic_set_rxfh(struct net_device *netdev, const u32 *indir, const u8 *key, const u8 hfunc) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int err = 0; - - if (!test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Not support to set rss parameters when rss is disable\n"); - return -EOPNOTSUPP; - } - - if (test_bit(SPNIC_DCB_ENABLE, &nic_dev->flags) && indir) { - nicif_err(nic_dev, drv, netdev, "Not support to set indir when DCB is enabled\n"); - return -EOPNOTSUPP; - } - - if (hfunc != ETH_RSS_HASH_NO_CHANGE) { - if (hfunc != ETH_RSS_HASH_TOP && hfunc != ETH_RSS_HASH_XOR) { - nicif_err(nic_dev, drv, netdev, "Not support to set hfunc type except TOP and XOR\n"); - return -EOPNOTSUPP; - } - - nic_dev->rss_hash_engine = (hfunc == ETH_RSS_HASH_XOR) ? - SPNIC_RSS_HASH_ENGINE_TYPE_XOR : - SPNIC_RSS_HASH_ENGINE_TYPE_TOEP; - err = spnic_rss_set_hash_engine(nic_dev->hwdev, nic_dev->rss_hash_engine); - if (err) - return -EFAULT; - - nicif_info(nic_dev, drv, netdev, "Change hfunc to RSS_HASH_%s success\n", - (hfunc == ETH_RSS_HASH_XOR) ? "XOR" : "TOP"); - } - err = set_rss_rxfh(netdev, indir, key); - - return err; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_rss.h b/drivers/net/ethernet/ramaxel/spnic/spnic_rss.h deleted file mode 100644 index e64a4dcf39dd..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_rss.h +++ /dev/null @@ -1,50 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_RSS_H -#define SPNIC_RSS_H - -#include "spnic_nic_dev.h" - -int spnic_rss_init(struct spnic_nic_dev *nic_dev); - -void spnic_rss_deinit(struct spnic_nic_dev *nic_dev); - -int spnic_set_hw_rss_parameters(struct net_device *netdev, u8 rss_en, u8 num_tc, u8 *prio_tc); - -void spnic_init_rss_parameters(struct net_device *netdev); - -void spnic_set_default_rss_indir(struct net_device *netdev); - -void spnic_try_to_enable_rss(struct spnic_nic_dev *nic_dev); - -void spnic_clear_rss_config(struct spnic_nic_dev *nic_dev); - -void spnic_flush_rx_flow_rule(struct spnic_nic_dev *nic_dev); -int spnic_ethtool_get_flow(struct spnic_nic_dev *nic_dev, struct ethtool_rxnfc *info, u32 location); - -int spnic_ethtool_get_all_flows(struct spnic_nic_dev *nic_dev, - struct ethtool_rxnfc *info, u32 *rule_locs); - -int spnic_ethtool_flow_remove(struct spnic_nic_dev *nic_dev, u32 location); - -int spnic_ethtool_flow_replace(struct spnic_nic_dev *nic_dev, struct ethtool_rx_flow_spec *fs); - -/* for ethtool */ -int spnic_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, u32 *rule_locs); - -int spnic_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd); - -void spnic_get_channels(struct net_device *netdev, struct ethtool_channels *channels); - -int spnic_set_channels(struct net_device *netdev, struct ethtool_channels *channels); - -u32 spnic_get_rxfh_indir_size(struct net_device *netdev); - -u32 spnic_get_rxfh_key_size(struct net_device *netdev); - -int spnic_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc); - -int spnic_set_rxfh(struct net_device *netdev, const u32 *indir, const u8 *key, const u8 hfunc); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_rss_cfg.c b/drivers/net/ethernet/ramaxel/spnic/spnic_rss_cfg.c deleted file mode 100644 index 12da3aa59400..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_rss_cfg.c +++ /dev/null @@ -1,333 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/kernel.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/dcbnl.h> - -#include "sphw_crm.h" -#include "spnic_nic_cfg.h" -#include "sphw_hw.h" -#include "spnic_nic.h" -#include "sphw_common.h" - -static int spnic_rss_cfg_hash_key(struct spnic_nic_cfg *nic_cfg, u8 opcode, u8 *key) -{ - struct spnic_cmd_rss_hash_key hash_key; - u16 out_size = sizeof(hash_key); - int err; - - memset(&hash_key, 0, sizeof(struct spnic_cmd_rss_hash_key)); - hash_key.func_id = sphw_global_func_id(nic_cfg->hwdev); - hash_key.opcode = opcode; - - if (opcode == SPNIC_CMD_OP_SET) - memcpy(hash_key.key, key, SPNIC_RSS_KEY_SIZE); - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, - SPNIC_NIC_CMD_CFG_RSS_HASH_KEY, - &hash_key, sizeof(hash_key), - &hash_key, &out_size); - if (err || !out_size || hash_key.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to %s hash key, err: %d, status: 0x%x, out size: 0x%x\n", - opcode == SPNIC_CMD_OP_SET ? "set" : "get", - err, hash_key.msg_head.status, out_size); - return -EINVAL; - } - - if (opcode == SPNIC_CMD_OP_GET) - memcpy(key, hash_key.key, SPNIC_RSS_KEY_SIZE); - - return 0; -} - -int spnic_rss_set_hash_key(void *hwdev, const u8 *key) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - u8 hash_key[SPNIC_RSS_KEY_SIZE]; - - if (!hwdev || !key) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memcpy(hash_key, key, SPNIC_RSS_KEY_SIZE); - return spnic_rss_cfg_hash_key(nic_cfg, SPNIC_CMD_OP_SET, hash_key); -} - -int spnic_rss_get_hash_key(void *hwdev, u8 *key) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev || !key) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - return spnic_rss_cfg_hash_key(nic_cfg, SPNIC_CMD_OP_GET, key); -} - -int spnic_rss_get_indir_tbl(void *hwdev, u32 *indir_table) -{ - struct sphw_cmd_buf *cmd_buf = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - u16 *indir_tbl = NULL; - int err, i; - - if (!hwdev || !indir_table) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - cmd_buf = sphw_alloc_cmd_buf(hwdev); - if (!cmd_buf) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate cmd_buf.\n"); - return -ENOMEM; - } - - cmd_buf->size = sizeof(struct nic_rss_indirect_tbl); - err = sphw_cmdq_detail_resp(hwdev, SPHW_MOD_L2NIC, SPNIC_UCODE_CMD_GET_RSS_INDIR_TABLE, - cmd_buf, cmd_buf, NULL, 0, SPHW_CHANNEL_NIC); - if (err) { - nic_err(nic_cfg->dev_hdl, "Failed to get rss indir table\n"); - goto get_indir_tbl_failed; - } - - indir_tbl = (u16 *)cmd_buf->buf; - for (i = 0; i < SPNIC_RSS_INDIR_SIZE; i++) - indir_table[i] = *(indir_tbl + i); - -get_indir_tbl_failed: - sphw_free_cmd_buf(hwdev, cmd_buf); - - return err; -} - -int spnic_rss_set_indir_tbl(void *hwdev, const u32 *indir_table) -{ - struct nic_rss_indirect_tbl *indir_tbl = NULL; - struct sphw_cmd_buf *cmd_buf = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - u32 *temp = NULL; - u32 i, size; - u64 out_param = 0; - int err; - - if (!hwdev || !indir_table) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - cmd_buf = sphw_alloc_cmd_buf(hwdev); - if (!cmd_buf) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate cmd buf\n"); - return -ENOMEM; - } - - cmd_buf->size = sizeof(struct nic_rss_indirect_tbl); - indir_tbl = (struct nic_rss_indirect_tbl *)cmd_buf->buf; - memset(indir_tbl, 0, sizeof(*indir_tbl)); - - for (i = 0; i < SPNIC_RSS_INDIR_SIZE; i++) - indir_tbl->entry[i] = (u16)(*(indir_table + i)); - - size = sizeof(indir_tbl->entry) / sizeof(u32); - temp = (u32 *)indir_tbl->entry; - for (i = 0; i < size; i++) - temp[i] = cpu_to_be32(temp[i]); - - err = sphw_cmdq_direct_resp(hwdev, SPHW_MOD_L2NIC, SPNIC_UCODE_CMD_SET_RSS_INDIR_TABLE, - cmd_buf, &out_param, 0, SPHW_CHANNEL_NIC); - if (err || out_param != 0) { - nic_err(nic_cfg->dev_hdl, "Failed to set rss indir table\n"); - err = -EFAULT; - } - - sphw_free_cmd_buf(hwdev, cmd_buf); - return err; -} - -#define SPNIC_RSS_TYPE_VALID_SHIFT 23 -#define SPNIC_RSS_TYPE_TCP_IPV6_EXT_SHIFT 24 -#define SPNIC_RSS_TYPE_IPV6_EXT_SHIFT 25 -#define SPNIC_RSS_TYPE_TCP_IPV6_SHIFT 26 -#define SPNIC_RSS_TYPE_IPV6_SHIFT 27 -#define SPNIC_RSS_TYPE_TCP_IPV4_SHIFT 28 -#define SPNIC_RSS_TYPE_IPV4_SHIFT 29 -#define SPNIC_RSS_TYPE_UDP_IPV6_SHIFT 30 -#define SPNIC_RSS_TYPE_UDP_IPV4_SHIFT 31 -#define SPNIC_RSS_TYPE_SET(val, member) (((u32)(val) & 0x1) << SPNIC_RSS_TYPE_##member##_SHIFT) - -#define SPNIC_RSS_TYPE_GET(val, member) (((u32)(val) >> SPNIC_RSS_TYPE_##member##_SHIFT) & 0x1) - -int spnic_set_rss_type(void *hwdev, struct nic_rss_type rss_type) -{ - struct nic_rss_context_tbl *ctx_tbl = NULL; - struct sphw_cmd_buf *cmd_buf = NULL; - struct spnic_nic_cfg *nic_cfg = NULL; - u32 ctx = 0; - u64 out_param = 0; - int err; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - cmd_buf = sphw_alloc_cmd_buf(hwdev); - if (!cmd_buf) { - nic_err(nic_cfg->dev_hdl, "Failed to allocate cmd buf\n"); - return -ENOMEM; - } - - ctx |= SPNIC_RSS_TYPE_SET(1, VALID) | - SPNIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) | - SPNIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) | - SPNIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) | - SPNIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) | - SPNIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) | - SPNIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) | - SPNIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) | - SPNIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6); - - cmd_buf->size = sizeof(struct nic_rss_context_tbl); - ctx_tbl = (struct nic_rss_context_tbl *)cmd_buf->buf; - memset(ctx_tbl, 0, sizeof(*ctx_tbl)); - ctx_tbl->ctx = cpu_to_be32(ctx); - - /* cfg the rss context table by command queue */ - err = sphw_cmdq_direct_resp(hwdev, SPHW_MOD_L2NIC, SPNIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE, - cmd_buf, &out_param, 0, SPHW_CHANNEL_NIC); - - sphw_free_cmd_buf(hwdev, cmd_buf); - - if (err || out_param != 0) { - nic_err(nic_cfg->dev_hdl, "Failed to set rss context table, err: %d\n", - err); - return -EFAULT; - } - - return 0; -} - -int spnic_get_rss_type(void *hwdev, struct nic_rss_type *rss_type) -{ - struct spnic_rss_context_table ctx_tbl; - u16 out_size = sizeof(ctx_tbl); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - if (!hwdev || !rss_type) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - - memset(&ctx_tbl, 0, sizeof(struct spnic_rss_context_table)); - ctx_tbl.func_id = sphw_global_func_id(hwdev); - - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_GET_RSS_CTX_TBL, - &ctx_tbl, sizeof(ctx_tbl), - &ctx_tbl, &out_size); - if (err || !out_size || ctx_tbl.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to get hash type, err: %d, status: 0x%x, out size: 0x%x\n", - err, ctx_tbl.msg_head.status, out_size); - return -EINVAL; - } - - rss_type->ipv4 = SPNIC_RSS_TYPE_GET(ctx_tbl.context, IPV4); - rss_type->ipv6 = SPNIC_RSS_TYPE_GET(ctx_tbl.context, IPV6); - rss_type->ipv6_ext = SPNIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT); - rss_type->tcp_ipv4 = SPNIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4); - rss_type->tcp_ipv6 = SPNIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6); - rss_type->tcp_ipv6_ext = SPNIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6_EXT); - rss_type->udp_ipv4 = SPNIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4); - rss_type->udp_ipv6 = SPNIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6); - - return 0; -} - -static int spnic_rss_cfg_hash_engine(struct spnic_nic_cfg *nic_cfg, u8 opcode, u8 *type) -{ - struct spnic_cmd_rss_engine_type hash_type; - u16 out_size = sizeof(hash_type); - int err; - - memset(&hash_type, 0, sizeof(struct spnic_cmd_rss_engine_type)); - - hash_type.func_id = sphw_global_func_id(nic_cfg->hwdev); - hash_type.opcode = opcode; - - if (opcode == SPNIC_CMD_OP_SET) - hash_type.hash_engine = *type; - - err = l2nic_msg_to_mgmt_sync(nic_cfg->hwdev, SPNIC_NIC_CMD_CFG_RSS_HASH_ENGINE, - &hash_type, sizeof(hash_type), - &hash_type, &out_size); - if (err || !out_size || hash_type.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to %s hash engine, err: %d, status: 0x%x, out size: 0x%x\n", - opcode == SPNIC_CMD_OP_SET ? "set" : "get", - err, hash_type.msg_head.status, out_size); - return -EIO; - } - - if (opcode == SPNIC_CMD_OP_GET) - *type = hash_type.hash_engine; - - return 0; -} - -int spnic_rss_set_hash_engine(void *hwdev, u8 type) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - return spnic_rss_cfg_hash_engine(nic_cfg, SPNIC_CMD_OP_SET, &type); -} - -int spnic_rss_get_hash_engine(void *hwdev, u8 *type) -{ - struct spnic_nic_cfg *nic_cfg = NULL; - - if (!hwdev || !type) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - return spnic_rss_cfg_hash_engine(nic_cfg, SPNIC_CMD_OP_GET, type); -} - -int spnic_rss_cfg(void *hwdev, u8 rss_en, u8 tc_num, u8 *prio_tc, u16 num_qps) -{ - struct spnic_cmd_rss_config rss_cfg; - u16 out_size = sizeof(rss_cfg); - struct spnic_nic_cfg *nic_cfg = NULL; - int err; - - /* micro code required: number of TC should be power of 2 */ - if (!hwdev || !prio_tc || (tc_num & (tc_num - 1))) - return -EINVAL; - - nic_cfg = sphw_get_service_adapter(hwdev, SERVICE_T_NIC); - memset(&rss_cfg, 0, sizeof(struct spnic_cmd_rss_config)); - rss_cfg.func_id = sphw_global_func_id(hwdev); - rss_cfg.rss_en = rss_en; - rss_cfg.rq_priority_number = tc_num ? (u8)ilog2(tc_num) : 0; - rss_cfg.num_qps = num_qps; - - memcpy(rss_cfg.prio_tc, prio_tc, SPNIC_DCB_UP_MAX); - err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_NIC_CMD_RSS_CFG, - &rss_cfg, sizeof(rss_cfg), - &rss_cfg, &out_size); - if (err || !out_size || rss_cfg.msg_head.status) { - nic_err(nic_cfg->dev_hdl, "Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x\n", - err, rss_cfg.msg_head.status, out_size); - return -EINVAL; - } - - return 0; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_rx.c b/drivers/net/ethernet/ramaxel/spnic/spnic_rx.c deleted file mode 100644 index 3ae2f15c727b..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_rx.c +++ /dev/null @@ -1,1238 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/skbuff.h> -#include <linux/dma-mapping.h> -#include <linux/interrupt.h> -#include <linux/etherdevice.h> -#include <linux/netdevice.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/u64_stats_sync.h> -#include <linux/ip.h> -#include <linux/tcp.h> -#include <linux/sctp.h> -#include <linux/pkt_sched.h> -#include <linux/ipv6.h> -#include <linux/module.h> -#include <linux/compiler.h> - -#include "sphw_crm.h" -#include "sphw_common.h" -#include "spnic_nic_qp.h" -#include "spnic_nic_io.h" -#include "spnic_nic_dev.h" -#include "spnic_rx.h" -#include "spnic_rss.h" - -static u32 rq_pi_rd_en; -module_param(rq_pi_rd_en, uint, 0644); -MODULE_PARM_DESC(rq_pi_rd_en, "Enable rq read pi from host, defaut update pi by doorbell (default=0)"); - -/* performance: ci addr RTE_CACHE_SIZE(64B) alignment */ -#define SPNIC_RX_HDR_SIZE 256 -#define SPNIC_RX_BUFFER_WRITE 16 - -#define SPNIC_RX_TCP_PKT 0x3 -#define SPNIC_RX_UDP_PKT 0x4 -#define SPNIC_RX_SCTP_PKT 0x7 - -#define SPNIC_RX_IPV4_PKT 0 -#define SPNIC_RX_IPV6_PKT 1 -#define SPNIC_RX_INVALID_IP_TYPE 2 - -#define SPNIC_RX_PKT_FORMAT_NON_TUNNEL 0 -#define SPNIC_RX_PKT_FORMAT_VXLAN 1 - -#define RXQ_STATS_INC(rxq, field) \ -do { \ - u64_stats_update_begin(&(rxq)->rxq_stats.syncp); \ - (rxq)->rxq_stats.field++; \ - u64_stats_update_end(&(rxq)->rxq_stats.syncp); \ -} while (0) - -static bool rx_alloc_mapped_page(struct spnic_nic_dev *nic_dev, - struct spnic_rx_info *rx_info) -{ - struct pci_dev *pdev = nic_dev->pdev; - struct page *page = rx_info->page; - dma_addr_t dma = rx_info->buf_dma_addr; - - if (likely(dma)) - return true; - - /* alloc new page for storage */ - page = alloc_pages_node(NUMA_NO_NODE, GFP_ATOMIC | __GFP_COMP, nic_dev->page_order); - if (unlikely(!page)) - return false; - - /* map page for use */ - dma = dma_map_page(&pdev->dev, page, 0, nic_dev->dma_rx_buff_size, DMA_FROM_DEVICE); - - /* if mapping failed free memory back to system since - * there isn't much point in holding memory we can't use - */ - if (unlikely(dma_mapping_error(&pdev->dev, dma))) { - __free_pages(page, nic_dev->page_order); - return false; - } - - rx_info->page = page; - rx_info->buf_dma_addr = dma; - rx_info->page_offset = 0; - - return true; -} - -static u32 spnic_rx_fill_wqe(struct spnic_rxq *rxq) -{ - struct net_device *netdev = rxq->netdev; - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_rq_wqe *rq_wqe = NULL; - struct spnic_rx_info *rx_info = NULL; - u32 i; - - for (i = 0; i < rxq->q_depth; i++) { - rx_info = &rxq->rx_info[i]; - rq_wqe = spnic_rq_wqe_addr(rxq->rq, (u16)i); - - if (rxq->rq->wqe_type == SPNIC_EXTEND_RQ_WQE) { - /* unit of cqe length is 16B */ - sphw_set_sge(&rq_wqe->extend_wqe.cqe_sect.sge, rx_info->cqe_dma, - (sizeof(struct spnic_rq_cqe) >> SPNIC_CQE_SIZE_SHIFT)); - /* use fixed len */ - rq_wqe->extend_wqe.buf_desc.sge.len = - nic_dev->rx_buff_len; - } else { - rq_wqe->normal_wqe.cqe_hi_addr = upper_32_bits(rx_info->cqe_dma); - rq_wqe->normal_wqe.cqe_lo_addr = lower_32_bits(rx_info->cqe_dma); - } - - rx_info->rq_wqe = rq_wqe; - } - - return i; -} - -static struct sk_buff *stub_rx_alloc_skb(struct spnic_rxq *rxq, struct spnic_rx_info *rx_info) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(rxq->netdev); - struct sk_buff *skb = NULL; - u16 random_id; - dma_addr_t addr; - int err; - - get_random_bytes(&random_id, sizeof(u16)); - - rx_info->skb_len = SPNIC_RX_HDR_SIZE + (random_id & 0x3EFF); - skb = netdev_alloc_skb_ip_align(rxq->netdev, rx_info->skb_len); - if (!skb) { - nicif_err(nic_dev, drv, rxq->netdev, "Failed to allocate Rx SKB\n"); - return NULL; - } - - addr = dma_map_single(&nic_dev->pdev->dev, skb->data, rx_info->skb_len, - DMA_FROM_DEVICE); - - err = dma_mapping_error(&nic_dev->pdev->dev, addr); - if (err) { - nicif_err(nic_dev, drv, rxq->netdev, "Failed to map Rx DMA, err = %d\n", err); - goto err_rx_map; - } - - rx_info->buf_dma_addr = addr; - - return skb; - -err_rx_map: - dev_kfree_skb_any(skb); - return NULL; -} - -static u32 stub_spnic_rx_fill_buffers(struct spnic_rxq *rxq) -{ - struct net_device *netdev = rxq->netdev; - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u32 i, free_wqebbs = rxq->delta - 1; - struct spnic_rq_wqe *rq_wqe = NULL; - struct spnic_rx_info *rx_info = NULL; - struct sk_buff *skb = NULL; - dma_addr_t dma_addr; - - for (i = 0; i < free_wqebbs; i++) { - rx_info = &rxq->rx_info[rxq->next_to_update]; - - skb = stub_rx_alloc_skb(rxq, rx_info); - if (!skb) { - nicif_err(nic_dev, drv, rxq->netdev, "Failed to alloc Rx skb\n"); - break; - } - - rq_wqe = rx_info->rq_wqe; - rx_info->saved_skb = skb; - dma_addr = rx_info->buf_dma_addr; - - if (rxq->rq->wqe_type == SPNIC_EXTEND_RQ_WQE) { - rq_wqe->extend_wqe.buf_desc.sge.hi_addr = upper_32_bits(dma_addr); - rq_wqe->extend_wqe.buf_desc.sge.lo_addr = lower_32_bits(dma_addr); - rq_wqe->extend_wqe.buf_desc.sge.len = rx_info->skb_len; - } else { - rq_wqe->normal_wqe.buf_hi_addr = upper_32_bits(dma_addr); - rq_wqe->normal_wqe.buf_lo_addr = lower_32_bits(dma_addr); - } - rxq->next_to_update = (rxq->next_to_update + 1) & rxq->q_mask; - } - - if (likely(i)) { - if (!rq_pi_rd_en) { - spnic_write_db(rxq->rq, rxq->q_id & (SPNIC_DCB_COS_MAX - 1), RQ_CFLAG_DP, - (u16)((u32)rxq->next_to_update << rxq->rq->wqe_type)); - } else { - /* Write all the wqes before pi update */ - wmb(); - - spnic_update_rq_hw_pi(rxq->rq, rxq->next_to_update); - } - rxq->delta -= i; - rxq->next_to_alloc = rxq->next_to_update; - } else { - nicif_err(nic_dev, drv, netdev, "Failed to allocate rx buffers, rxq id: %u\n", - rxq->q_id); - } - - return i; -} - -static u32 spnic_rx_fill_buffers(struct spnic_rxq *rxq) -{ - struct net_device *netdev = rxq->netdev; - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_rq_wqe *rq_wqe = NULL; - struct spnic_rx_info *rx_info = NULL; - dma_addr_t dma_addr; - u32 i, free_wqebbs = rxq->delta - 1; - - for (i = 0; i < free_wqebbs; i++) { - rx_info = &rxq->rx_info[rxq->next_to_update]; - - if (unlikely(!rx_alloc_mapped_page(nic_dev, rx_info))) { - RXQ_STATS_INC(rxq, alloc_rx_buf_err); - break; - } - - dma_addr = rx_info->buf_dma_addr + rx_info->page_offset; - - rq_wqe = rx_info->rq_wqe; - - if (rxq->rq->wqe_type == SPNIC_EXTEND_RQ_WQE) { - rq_wqe->extend_wqe.buf_desc.sge.hi_addr = upper_32_bits(dma_addr); - rq_wqe->extend_wqe.buf_desc.sge.lo_addr = lower_32_bits(dma_addr); - } else { - rq_wqe->normal_wqe.buf_hi_addr = upper_32_bits(dma_addr); - rq_wqe->normal_wqe.buf_lo_addr = lower_32_bits(dma_addr); - } - rxq->next_to_update = (rxq->next_to_update + 1) & rxq->q_mask; - } - - if (likely(i)) { - if (!rq_pi_rd_en) { - spnic_write_db(rxq->rq, rxq->q_id & (SPNIC_DCB_COS_MAX - 1), RQ_CFLAG_DP, - (u16)((u32)rxq->next_to_update << rxq->rq->wqe_type)); - } else { - /* Write all the wqes before pi update */ - wmb(); - - spnic_update_rq_hw_pi(rxq->rq, rxq->next_to_update); - } - rxq->delta -= i; - rxq->next_to_alloc = rxq->next_to_update; - } else if (free_wqebbs == rxq->q_depth - 1) { - RXQ_STATS_INC(rxq, rx_buf_empty); - } - - return i; -} - -static u32 spnic_rx_alloc_buffers(struct spnic_nic_dev *nic_dev, u32 rq_depth, - struct spnic_rx_info *rx_info_arr) -{ - u32 free_wqebbs = rq_depth - 1; - u32 idx; - - for (idx = 0; idx < free_wqebbs; idx++) { - if (!rx_alloc_mapped_page(nic_dev, &rx_info_arr[idx])) - break; - } - - return idx; -} - -void spnic_rx_free_buffers(struct spnic_nic_dev *nic_dev, u32 q_depth, - struct spnic_rx_info *rx_info_arr) -{ - struct spnic_rx_info *rx_info = NULL; - u32 i; - - /* Free all the Rx ring sk_buffs */ - for (i = 0; i < q_depth; i++) { - rx_info = &rx_info_arr[i]; - - if (rx_info->buf_dma_addr) { - dma_unmap_page(&nic_dev->pdev->dev, rx_info->buf_dma_addr, - nic_dev->dma_rx_buff_size, DMA_FROM_DEVICE); - rx_info->buf_dma_addr = 0; - } - - if (rx_info->page) { - __free_pages(rx_info->page, nic_dev->page_order); - rx_info->page = NULL; - } - } -} - -void stub_spnic_rx_free_buffers(struct spnic_rxq *rxq) -{ - struct spnic_rx_info *rx_info = NULL; - u32 i; - - /* Free all the Rx ring sk_buffs */ - for (i = 0; i < rxq->q_depth; i++) { - rx_info = &rxq->rx_info[i]; - - if (rx_info->buf_dma_addr) { - dma_unmap_page(rxq->dev, rx_info->buf_dma_addr, rx_info->skb_len, - DMA_FROM_DEVICE); - rx_info->buf_dma_addr = 0; - } - - if (rx_info->saved_skb) { - dev_kfree_skb_any(rx_info->saved_skb); - rx_info->saved_skb = NULL; - } - } -} - -static void spnic_reuse_rx_page(struct spnic_rxq *rxq, struct spnic_rx_info *old_rx_info) -{ - struct spnic_rx_info *new_rx_info; - u16 nta = rxq->next_to_alloc; - - new_rx_info = &rxq->rx_info[nta]; - - /* update, and store next to alloc */ - nta++; - rxq->next_to_alloc = (nta < rxq->q_depth) ? nta : 0; - - new_rx_info->page = old_rx_info->page; - new_rx_info->page_offset = old_rx_info->page_offset; - new_rx_info->buf_dma_addr = old_rx_info->buf_dma_addr; - - /* sync the buffer for use by the device */ - dma_sync_single_range_for_device(rxq->dev, new_rx_info->buf_dma_addr, - new_rx_info->page_offset, rxq->buf_len, - DMA_FROM_DEVICE); -} - -static bool spnic_add_rx_frag(struct spnic_rxq *rxq, struct spnic_rx_info *rx_info, - struct sk_buff *skb, u32 size) -{ - struct page *page; - u8 *va; - - page = rx_info->page; - va = (u8 *)page_address(page) + rx_info->page_offset; - prefetch(va); -#if L1_CACHE_BYTES < 128 - prefetch(va + L1_CACHE_BYTES); -#endif - - dma_sync_single_range_for_cpu(rxq->dev, rx_info->buf_dma_addr, - rx_info->page_offset, - rxq->buf_len, DMA_FROM_DEVICE); - - if (size <= SPNIC_RX_HDR_SIZE && !skb_is_nonlinear(skb)) { - memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long))); - - /* page is not reserved, we can reuse buffer as-is */ - if (likely(page_to_nid(page) == numa_node_id())) - return true; - - /* this page cannot be reused so discard it */ - put_page(page); - return false; - } - - skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, - (int)rx_info->page_offset, (int)size, rxq->buf_len); - - /* avoid re-using remote pages */ - if (unlikely(page_to_nid(page) != numa_node_id())) - return false; - - /* if we are only owner of page we can reuse it */ - if (unlikely(page_count(page) != 1)) - return false; - - /* flip page offset to other buffer */ - rx_info->page_offset ^= rxq->buf_len; - get_page(page); - - return true; -} - -static void packaging_skb(struct spnic_rxq *rxq, struct sk_buff *head_skb, u8 sge_num, u32 pkt_len) -{ - struct spnic_rx_info *rx_info = NULL; - struct sk_buff *skb = NULL; - u8 frag_num = 0; - u32 size; - u32 sw_ci; - - sw_ci = rxq->cons_idx & rxq->q_mask; - skb = head_skb; - while (sge_num) { - rx_info = &rxq->rx_info[sw_ci]; - sw_ci = (sw_ci + 1) & rxq->q_mask; - if (unlikely(pkt_len > rxq->buf_len)) { - size = rxq->buf_len; - pkt_len -= rxq->buf_len; - } else { - size = pkt_len; - } - - if (unlikely(frag_num == MAX_SKB_FRAGS)) { - frag_num = 0; - if (skb == head_skb) - skb = skb_shinfo(skb)->frag_list; - else - skb = skb->next; - } - - if (unlikely(skb != head_skb)) { - head_skb->len += size; - head_skb->data_len += size; - head_skb->truesize += rxq->buf_len; - } - - if (likely(spnic_add_rx_frag(rxq, rx_info, skb, size))) { - spnic_reuse_rx_page(rxq, rx_info); - } else { - /* we are not reusing the buffer so unmap it */ - dma_unmap_page(rxq->dev, rx_info->buf_dma_addr, - rxq->dma_rx_buff_size, DMA_FROM_DEVICE); - } - /* clear contents of buffer_info */ - rx_info->buf_dma_addr = 0; - rx_info->page = NULL; - sge_num--; - frag_num++; - } -} - -#define SPNIC_GET_SGE_NUM(pkt_len, rxq) \ - ((u8)(((pkt_len) >> (rxq)->rx_buff_shift) + \ - (((pkt_len) & ((rxq)->buf_len - 1)) ? 1 : 0))) - -static struct sk_buff *spnic_fetch_rx_buffer(struct spnic_rxq *rxq, u32 pkt_len) -{ - struct sk_buff *head_skb = NULL; - struct sk_buff *cur_skb = NULL; - struct sk_buff *skb = NULL; - struct net_device *netdev = rxq->netdev; - u8 sge_num, skb_num; - u16 wqebb_cnt = 0; - - head_skb = netdev_alloc_skb_ip_align(netdev, SPNIC_RX_HDR_SIZE); - if (unlikely(!head_skb)) - return NULL; - - sge_num = SPNIC_GET_SGE_NUM(pkt_len, rxq); - if (likely(sge_num <= MAX_SKB_FRAGS)) - skb_num = 1; - else - skb_num = (sge_num / MAX_SKB_FRAGS) + ((sge_num % MAX_SKB_FRAGS) ? 1 : 0); - - while (unlikely(skb_num > 1)) { - cur_skb = netdev_alloc_skb_ip_align(netdev, SPNIC_RX_HDR_SIZE); - if (unlikely(!cur_skb)) - goto alloc_skb_fail; - - if (!skb) { - skb_shinfo(head_skb)->frag_list = cur_skb; - skb = cur_skb; - } else { - skb->next = cur_skb; - skb = cur_skb; - } - - skb_num--; - } - - prefetchw(head_skb->data); - wqebb_cnt = sge_num; - - packaging_skb(rxq, head_skb, sge_num, pkt_len); - - rxq->cons_idx += wqebb_cnt; - rxq->delta += wqebb_cnt; - - return head_skb; - -alloc_skb_fail: - dev_kfree_skb_any(head_skb); - return NULL; -} - -void spnic_rxq_get_stats(struct spnic_rxq *rxq, struct spnic_rxq_stats *stats) -{ - struct spnic_rxq_stats *rxq_stats = &rxq->rxq_stats; - unsigned int start; - - u64_stats_update_begin(&stats->syncp); - do { - start = u64_stats_fetch_begin(&rxq_stats->syncp); - stats->bytes = rxq_stats->bytes; - stats->packets = rxq_stats->packets; - stats->errors = rxq_stats->csum_errors + - rxq_stats->other_errors; - stats->csum_errors = rxq_stats->csum_errors; - stats->other_errors = rxq_stats->other_errors; - stats->dropped = rxq_stats->dropped; - stats->xdp_dropped = rxq_stats->xdp_dropped; - stats->rx_buf_empty = rxq_stats->rx_buf_empty; - } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); - u64_stats_update_end(&stats->syncp); -} - -void spnic_rxq_clean_stats(struct spnic_rxq_stats *rxq_stats) -{ - u64_stats_update_begin(&rxq_stats->syncp); - rxq_stats->bytes = 0; - rxq_stats->packets = 0; - rxq_stats->errors = 0; - rxq_stats->csum_errors = 0; - rxq_stats->other_errors = 0; - rxq_stats->dropped = 0; - rxq_stats->xdp_dropped = 0; - rxq_stats->rx_buf_empty = 0; - - rxq_stats->alloc_skb_err = 0; - rxq_stats->alloc_rx_buf_err = 0; - rxq_stats->xdp_large_pkt = 0; - u64_stats_update_end(&rxq_stats->syncp); -} - -static void rxq_stats_init(struct spnic_rxq *rxq) -{ - struct spnic_rxq_stats *rxq_stats = &rxq->rxq_stats; - - u64_stats_init(&rxq_stats->syncp); - spnic_rxq_clean_stats(rxq_stats); -} - -static void spnic_pull_tail(struct sk_buff *skb) -{ - skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; - unsigned char *va = NULL; - unsigned int pull_len; - - /* it is valid to use page_address instead of kmap since we are - * working with pages allocated out of the lomem pool per - * alloc_page(GFP_ATOMIC) - */ - va = skb_frag_address(frag); - - /* we need the header to contain the greater of either ETH_HLEN or - * 60 bytes if the skb->len is less than 60 for skb_pad. - */ - pull_len = eth_get_headlen(skb->dev, va, SPNIC_RX_HDR_SIZE); - - /* align pull length to size of long to optimize memcpy performance */ - skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long))); - - /* update all of the pointers */ - skb_frag_size_sub(frag, (int)pull_len); - skb_frag_off_add(frag, (int)pull_len); - - skb->data_len -= pull_len; - skb->tail += pull_len; -} - -static void spnic_rx_csum(struct spnic_rxq *rxq, u32 offload_type, u32 status, struct sk_buff *skb) -{ - struct net_device *netdev = rxq->netdev; - u32 pkt_type = SPNIC_GET_RX_PKT_TYPE(offload_type); - u32 ip_type = SPNIC_GET_RX_IP_TYPE(offload_type); - u32 pkt_fmt = SPNIC_GET_RX_TUNNEL_PKT_FORMAT(offload_type); - - u32 csum_err; - - csum_err = SPNIC_GET_RX_CSUM_ERR(status); - - if (unlikely(csum_err == SPNIC_RX_CSUM_IPSU_OTHER_ERR)) - rxq->rxq_stats.other_errors++; - - if (!(netdev->features & NETIF_F_RXCSUM)) - return; - - if (unlikely(csum_err)) { - /* pkt type is recognized by HW, and csum is wrong */ - if (!(csum_err & (SPNIC_RX_CSUM_HW_CHECK_NONE | SPNIC_RX_CSUM_IPSU_OTHER_ERR))) - rxq->rxq_stats.csum_errors++; - skb->ip_summed = CHECKSUM_NONE; - return; - } - - if (ip_type == SPNIC_RX_INVALID_IP_TYPE || - !(pkt_fmt == SPNIC_RX_PKT_FORMAT_NON_TUNNEL || - pkt_fmt == SPNIC_RX_PKT_FORMAT_VXLAN)) { - skb->ip_summed = CHECKSUM_NONE; - return; - } - - switch (pkt_type) { - case SPNIC_RX_TCP_PKT: - case SPNIC_RX_UDP_PKT: - case SPNIC_RX_SCTP_PKT: - skb->ip_summed = CHECKSUM_UNNECESSARY; - break; - default: - skb->ip_summed = CHECKSUM_NONE; - break; - } -} - -static void spnic_rx_gro(struct spnic_rxq *rxq, u32 offload_type, struct sk_buff *skb) -{ - struct net_device *netdev = rxq->netdev; - bool l2_tunnel = false; - - if (!(netdev->features & NETIF_F_GRO)) - return; - - l2_tunnel = - SPNIC_GET_RX_TUNNEL_PKT_FORMAT(offload_type) == SPNIC_RX_PKT_FORMAT_VXLAN ? 1 : 0; - - if (l2_tunnel && skb->ip_summed == CHECKSUM_UNNECESSARY) - /* If we checked the outer header let the stack know */ - skb->csum_level = 1; -} - -static void spnic_copy_lp_data(struct spnic_nic_dev *nic_dev, struct sk_buff *skb) -{ - struct net_device *netdev = nic_dev->netdev; - u8 *lb_buf = nic_dev->lb_test_rx_buf; - void *frag_data = NULL; - int lb_len = nic_dev->lb_pkt_len; - int pkt_offset, frag_len, i; - - if (nic_dev->lb_test_rx_idx == LP_PKT_CNT) { - nic_dev->lb_test_rx_idx = 0; - nicif_warn(nic_dev, rx_err, netdev, "Loopback test warning, receive too many test pkts\n"); - } - - if (skb->len != nic_dev->lb_pkt_len) { - nicif_warn(nic_dev, rx_err, netdev, "Wrong packet length\n"); - nic_dev->lb_test_rx_idx++; - return; - } - - pkt_offset = nic_dev->lb_test_rx_idx * lb_len; - frag_len = (int)skb_headlen(skb); - memcpy(lb_buf + pkt_offset, skb->data, frag_len); - - pkt_offset += frag_len; - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - frag_data = skb_frag_address(&skb_shinfo(skb)->frags[i]); - frag_len = (int)skb_frag_size(&skb_shinfo(skb)->frags[i]); - memcpy(lb_buf + pkt_offset, frag_data, frag_len); - - pkt_offset += frag_len; - } - nic_dev->lb_test_rx_idx++; -} - -static inline void spnic_lro_set_gso_params(struct sk_buff *skb, u16 num_lro) -{ - struct ethhdr *eth = (struct ethhdr *)(skb->data); - __be16 proto; - - proto = __vlan_get_protocol(skb, eth->h_proto, NULL); - - skb_shinfo(skb)->gso_size = (u16)DIV_ROUND_UP((skb->len - skb_headlen(skb)), num_lro); - skb_shinfo(skb)->gso_type = (proto == htons(ETH_P_IP)) ? SKB_GSO_TCPV4 : SKB_GSO_TCPV6; -} - -enum spnic_xdp_pkt { - SPNIC_XDP_PKT_PASS, - SPNIC_XDP_PKT_DROP, -}; - -static inline void update_drop_rx_info(struct spnic_rxq *rxq, u16 weqbb_num) -{ - struct spnic_rx_info *rx_info = NULL; - - while (weqbb_num) { - rx_info = &rxq->rx_info[rxq->cons_idx & rxq->q_mask]; - if (likely(page_to_nid(rx_info->page) == numa_node_id())) - spnic_reuse_rx_page(rxq, rx_info); - - rx_info->buf_dma_addr = 0; - rx_info->page = NULL; - rxq->cons_idx++; - rxq->delta++; - - weqbb_num--; - } -} - -int spnic_run_xdp(struct spnic_rxq *rxq, u32 pkt_len) -{ - struct bpf_prog *xdp_prog = NULL; - struct spnic_rx_info *rx_info = NULL; - struct xdp_buff xdp; - int result = SPNIC_XDP_PKT_PASS; - u16 weqbb_num = 1; /* xdp can only use one rx_buff */ - u8 *va = NULL; - u32 act; - - rcu_read_lock(); - xdp_prog = READ_ONCE(rxq->xdp_prog); - if (!xdp_prog) - goto unlock_rcu; - - if (unlikely(pkt_len > rxq->buf_len)) { - RXQ_STATS_INC(rxq, xdp_large_pkt); - weqbb_num = (u16)(pkt_len >> rxq->rx_buff_shift) + - ((pkt_len & (rxq->buf_len - 1)) ? 1 : 0); - result = SPNIC_XDP_PKT_DROP; - goto xdp_out; - } - - rx_info = &rxq->rx_info[rxq->cons_idx & rxq->q_mask]; - va = (u8 *)page_address(rx_info->page) + rx_info->page_offset; - prefetch(va); - dma_sync_single_range_for_cpu(rxq->dev, rx_info->buf_dma_addr, rx_info->page_offset, - rxq->buf_len, DMA_FROM_DEVICE); - xdp.data = va; - xdp.data_hard_start = xdp.data; - xdp.data_end = xdp.data + pkt_len; - xdp.frame_sz = rxq->buf_len; - xdp_set_data_meta_invalid(&xdp); - prefetchw(xdp.data_hard_start); - act = bpf_prog_run_xdp(xdp_prog, &xdp); - switch (act) { - case XDP_PASS: - break; - case XDP_DROP: - result = SPNIC_XDP_PKT_DROP; - break; - default: - result = SPNIC_XDP_PKT_DROP; - bpf_warn_invalid_xdp_action(act); - } - -xdp_out: - if (result == SPNIC_XDP_PKT_DROP) { - RXQ_STATS_INC(rxq, xdp_dropped); - update_drop_rx_info(rxq, weqbb_num); - } - -unlock_rcu: - rcu_read_unlock(); - - return result; -} - -int recv_one_pkt(struct spnic_rxq *rxq, struct spnic_rq_cqe *rx_cqe, - u32 pkt_len, u32 vlan_len, u32 status) -{ - struct sk_buff *skb; - struct net_device *netdev = rxq->netdev; - u32 offload_type; - u16 num_lro; - struct spnic_nic_dev *nic_dev = netdev_priv(rxq->netdev); - - u32 xdp_status; - - xdp_status = spnic_run_xdp(rxq, pkt_len); - if (xdp_status == SPNIC_XDP_PKT_DROP) - return 0; - - skb = spnic_fetch_rx_buffer(rxq, pkt_len); - if (unlikely(!skb)) { - RXQ_STATS_INC(rxq, alloc_skb_err); - return -ENOMEM; - } - - /* place header in linear portion of buffer */ - if (skb_is_nonlinear(skb)) - spnic_pull_tail(skb); - - offload_type = rx_cqe->offload_type; - spnic_rx_csum(rxq, offload_type, status, skb); - - spnic_rx_gro(rxq, offload_type, skb); - - if ((netdev->features & NETIF_F_HW_VLAN_CTAG_RX) && - SPNIC_GET_RX_VLAN_OFFLOAD_EN(offload_type)) { - u16 vid = SPNIC_GET_RX_VLAN_TAG(vlan_len); - - /* if the packet is a vlan pkt, the vid may be 0 */ - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); - } - - if (unlikely(test_bit(SPNIC_LP_TEST, &nic_dev->flags))) - spnic_copy_lp_data(nic_dev, skb); - - num_lro = SPNIC_GET_RX_NUM_LRO(status); - if (num_lro) - spnic_lro_set_gso_params(skb, num_lro); - - skb_record_rx_queue(skb, rxq->q_id); - skb->protocol = eth_type_trans(skb, netdev); - - if (skb_has_frag_list(skb)) { - napi_gro_flush(&rxq->irq_cfg->napi, false); - netif_receive_skb(skb); - } else { - napi_gro_receive(&rxq->irq_cfg->napi, skb); - } - - return 0; -} - -void rx_pass_super_cqe(struct spnic_rxq *rxq, u32 index, u32 pkt_num, struct spnic_rq_cqe *cqe) -{ - u8 sge_num = 0; - u32 pkt_len; - - while (index < pkt_num) { - pkt_len = spnic_get_pkt_len_for_super_cqe(cqe, index == (pkt_num - 1)); - sge_num += (u8)(pkt_len >> rxq->rx_buff_shift) + - ((pkt_len & (rxq->buf_len - 1)) ? 1 : 0); - index++; - } - - rxq->cons_idx += sge_num; - rxq->delta += sge_num; -} - -static inline int recv_supper_cqe(struct spnic_rxq *rxq, struct spnic_rq_cqe *rx_cqe, u32 pkt_info, - u32 vlan_len, u32 status, int *pkts, u64 *rx_bytes, u32 *dropped) -{ - u32 pkt_len; - int i, pkt_num = 0; - - pkt_num = SPNIC_GET_RQ_CQE_PKT_NUM(pkt_info); - i = 0; - while (i < pkt_num) { - pkt_len = ((i == (pkt_num - 1)) ? - RQ_CQE_PKT_LEN_GET(pkt_info, LAST_LEN) : - RQ_CQE_PKT_LEN_GET(pkt_info, FIRST_LEN)); - if (unlikely(recv_one_pkt(rxq, rx_cqe, pkt_len, vlan_len, status))) { - if (i) { - rx_pass_super_cqe(rxq, i, pkt_num, rx_cqe); - *dropped += (pkt_num - i); - } - break; - } - - *rx_bytes += pkt_len; - (*pkts)++; - i++; - } - - if (!i) - return -EFAULT; - - return 0; -} - -#define LRO_PKT_HDR_LEN_IPV4 66 -#define LRO_PKT_HDR_LEN_IPV6 86 -#define LRO_PKT_HDR_LEN(cqe) \ - (SPNIC_GET_RX_IP_TYPE((cqe)->offload_type) == \ - SPNIC_RX_IPV6_PKT ? LRO_PKT_HDR_LEN_IPV6 : LRO_PKT_HDR_LEN_IPV4) - -static void stub_rx_recv_jumbo_pkt(struct spnic_rxq *rxq, struct sk_buff *head_skb, - unsigned int left_pkt_len) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(rxq->netdev); - struct sk_buff *skb = NULL; - struct sk_buff *curr_skb = head_skb; - struct spnic_rx_info *rx_info = NULL; - unsigned int curr_len; - - while (left_pkt_len > 0) { - rx_info = &rxq->rx_info[rxq->cons_idx & rxq->q_mask]; - skb = rx_info->saved_skb; - - dma_unmap_single(&nic_dev->pdev->dev, rx_info->buf_dma_addr, - rx_info->skb_len, DMA_FROM_DEVICE); - - rx_info->buf_dma_addr = 0; - rx_info->saved_skb = NULL; - - prefetch(skb->data); - - curr_len = (left_pkt_len > rx_info->skb_len) ? rx_info->skb_len : left_pkt_len; - - left_pkt_len -= curr_len; - - __skb_put(skb, curr_len); - - if (curr_skb == head_skb) - skb_shinfo(head_skb)->frag_list = skb; - else - curr_skb->next = skb; - - head_skb->len += skb->len; - head_skb->data_len += skb->len; - head_skb->truesize += skb->truesize; - - curr_skb = skb; - rxq->cons_idx++; - rxq->delta++; - } -} - -int stub_spnic_rx_poll(struct spnic_rxq *rxq, int budget) -{ - u32 sw_ci, status, pkt_len, vlan_len = 0; - struct spnic_nic_dev *nic_dev = netdev_priv(rxq->netdev); - struct spnic_rq_cqe *rx_cqe = NULL; - u64 rx_bytes = 0; - int pkts = 0; - struct sk_buff *skb = NULL; - struct spnic_rx_info *rx_info = NULL; - u32 offload_type; - - while (likely(pkts < budget)) { - sw_ci = rxq->cons_idx & rxq->q_mask; - rx_info = &rxq->rx_info[sw_ci]; - rx_cqe = rxq->rx_info[sw_ci].cqe; - status = be32_to_cpu(rx_cqe->status); - - if (!SPNIC_GET_RX_DONE(status)) - break; - - /* make sure we read rx_done before packet length */ - rmb(); - - vlan_len = be32_to_cpu(rx_cqe->vlan_len); - pkt_len = SPNIC_GET_RX_PKT_LEN(vlan_len); - skb = rx_info->saved_skb; - - dma_unmap_single(&nic_dev->pdev->dev, rx_info->buf_dma_addr, - rx_info->skb_len, DMA_FROM_DEVICE); - - rx_info->buf_dma_addr = 0; - rx_info->saved_skb = NULL; - - rxq->cons_idx++; - rxq->delta++; - - if (pkt_len <= rx_info->skb_len) { - __skb_put(skb, pkt_len); - } else { - __skb_put(skb, rx_info->skb_len); - stub_rx_recv_jumbo_pkt(rxq, skb, pkt_len - rx_info->skb_len); - } - - offload_type = be32_to_cpu(rx_cqe->offload_type); - spnic_rx_csum(rxq, offload_type, status, skb); - - spnic_rx_gro(rxq, offload_type, skb); - - skb_record_rx_queue(skb, rxq->q_id); - skb->protocol = eth_type_trans(skb, rxq->netdev); - - if (skb_has_frag_list(skb)) { - napi_gro_flush(&rxq->irq_cfg->napi, false); - netif_receive_skb(skb); - } else { - napi_gro_receive(&rxq->irq_cfg->napi, skb); - } - rx_bytes += pkt_len; - pkts++; - rx_cqe->status = 0; - } - - if (rxq->delta >= SPNIC_RX_BUFFER_WRITE) - stub_spnic_rx_fill_buffers(rxq); - - u64_stats_update_begin(&rxq->rxq_stats.syncp); - rxq->rxq_stats.packets += pkts; - rxq->rxq_stats.bytes += rx_bytes; - u64_stats_update_end(&rxq->rxq_stats.syncp); - return pkts; -} - -int spnic_rx_poll(struct spnic_rxq *rxq, int budget) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(rxq->netdev); - u32 sw_ci, status, pkt_len, vlan_len, pkt_info, dropped = 0; - struct spnic_rq_cqe *rx_cqe = NULL; - u64 rx_bytes = 0; - u16 num_lro; - int pkts = 0, nr_pkts = 0; - u16 num_wqe = 0; - - while (likely(pkts < budget)) { - sw_ci = rxq->cons_idx & rxq->q_mask; - rx_cqe = rxq->rx_info[sw_ci].cqe; - status = rx_cqe->status; - - if (!SPNIC_GET_RX_DONE(status)) - break; - - /* make sure we read rx_done before packet length */ - rmb(); - - vlan_len = rx_cqe->vlan_len; - pkt_info = rx_cqe->pkt_info; - pkt_len = SPNIC_GET_RX_PKT_LEN(vlan_len); - - if (unlikely(SPNIC_GET_SUPER_CQE_EN(pkt_info))) { - if (unlikely(recv_supper_cqe(rxq, rx_cqe, pkt_info, vlan_len, status, &pkts, - &rx_bytes, &dropped))) - break; - nr_pkts += (int)SPNIC_GET_RQ_CQE_PKT_NUM(pkt_info); - } else { - if (recv_one_pkt(rxq, rx_cqe, pkt_len, - vlan_len, status)) - break; - rx_bytes += pkt_len; - pkts++; - nr_pkts++; - - num_lro = SPNIC_GET_RX_NUM_LRO(status); - if (num_lro) { - rx_bytes += ((num_lro - 1) * LRO_PKT_HDR_LEN(rx_cqe)); - num_wqe += SPNIC_GET_SGE_NUM(pkt_len, rxq); - } - } - - rx_cqe->status = 0; - - if (num_wqe >= nic_dev->lro_replenish_thld) - break; - } - - if (rxq->delta >= SPNIC_RX_BUFFER_WRITE) - spnic_rx_fill_buffers(rxq); - - u64_stats_update_begin(&rxq->rxq_stats.syncp); - rxq->rxq_stats.packets += nr_pkts; - rxq->rxq_stats.bytes += rx_bytes; - rxq->rxq_stats.dropped += dropped; - u64_stats_update_end(&rxq->rxq_stats.syncp); - return pkts; -} - -int spnic_alloc_rxqs_res(struct spnic_nic_dev *nic_dev, u16 num_rq, - u32 rq_depth, struct spnic_dyna_rxq_res *rxqs_res) -{ - struct spnic_dyna_rxq_res *rqres = NULL; - u64 cqe_mem_size = sizeof(struct spnic_rq_cqe) * rq_depth; - int idx, i; - u32 pkts; - u64 size; - - for (idx = 0; idx < num_rq; idx++) { - rqres = &rxqs_res[idx]; - size = sizeof(*rqres->rx_info) * rq_depth; - rqres->rx_info = kzalloc(size, GFP_KERNEL); - if (!rqres->rx_info) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to alloc rxq%d rx info\n", idx); - goto err_out; - } - - rqres->cqe_start_vaddr = - dma_alloc_coherent(&nic_dev->pdev->dev, cqe_mem_size, - &rqres->cqe_start_paddr, GFP_KERNEL); - if (!rqres->cqe_start_vaddr) { - kfree(rqres->rx_info); - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to alloc rxq%d cqe\n", idx); - goto err_out; - } - - pkts = spnic_rx_alloc_buffers(nic_dev, rq_depth, rqres->rx_info); - if (!pkts) { - dma_free_coherent(&nic_dev->pdev->dev, cqe_mem_size, - rqres->cqe_start_vaddr, - rqres->cqe_start_paddr); - kfree(rqres->rx_info); - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to alloc rxq%d rx buffers\n", idx); - goto err_out; - } - rqres->next_to_alloc = (u16)pkts; - } - return 0; - -err_out: - for (i = 0; i < idx; i++) { - rqres = &rxqs_res[i]; - - spnic_rx_free_buffers(nic_dev, rq_depth, rqres->rx_info); - dma_free_coherent(&nic_dev->pdev->dev, cqe_mem_size, - rqres->cqe_start_vaddr, rqres->cqe_start_paddr); - kfree(rqres->rx_info); - } - - return -ENOMEM; -} - -void spnic_free_rxqs_res(struct spnic_nic_dev *nic_dev, u16 num_rq, - u32 rq_depth, struct spnic_dyna_rxq_res *rxqs_res) -{ - struct spnic_dyna_rxq_res *rqres = NULL; - u64 cqe_mem_size = sizeof(struct spnic_rq_cqe) * rq_depth; - int idx; - - for (idx = 0; idx < num_rq; idx++) { - rqres = &rxqs_res[idx]; - - spnic_rx_free_buffers(nic_dev, rq_depth, rqres->rx_info); - dma_free_coherent(&nic_dev->pdev->dev, cqe_mem_size, rqres->cqe_start_vaddr, - rqres->cqe_start_paddr); - kfree(rqres->rx_info); - } -} - -int spnic_configure_rxqs(struct spnic_nic_dev *nic_dev, u16 num_rq, - u32 rq_depth, struct spnic_dyna_rxq_res *rxqs_res) -{ - struct spnic_dyna_rxq_res *rqres = NULL; - struct irq_info *msix_entry = NULL; - struct spnic_rxq *rxq = NULL; - struct spnic_rq_cqe *cqe_va = NULL; - dma_addr_t cqe_pa; - u16 q_id; - u32 idx; - u32 pkts; - - for (q_id = 0; q_id < num_rq; q_id++) { - rxq = &nic_dev->rxqs[q_id]; - rqres = &rxqs_res[q_id]; - msix_entry = &nic_dev->qps_irq_info[q_id]; - - rxq->irq_id = msix_entry->irq_id; - rxq->msix_entry_idx = msix_entry->msix_entry_idx; - rxq->next_to_update = 0; - rxq->next_to_alloc = rqres->next_to_alloc; - rxq->q_depth = rq_depth; - rxq->delta = rxq->q_depth; - rxq->q_mask = rxq->q_depth - 1; - rxq->cons_idx = 0; - - rxq->rx_info = rqres->rx_info; - - /* fill cqe */ - cqe_va = (struct spnic_rq_cqe *)rqres->cqe_start_vaddr; - cqe_pa = rqres->cqe_start_paddr; - for (idx = 0; idx < rq_depth; idx++) { - rxq->rx_info[idx].cqe = cqe_va; - rxq->rx_info[idx].cqe_dma = cqe_pa; - cqe_va++; - cqe_pa += sizeof(*rxq->rx_info->cqe); - } - - rxq->rq = spnic_get_nic_queue(nic_dev->hwdev, rxq->q_id, SPNIC_RQ); - if (!rxq->rq) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to get rq\n"); - return -EINVAL; - } - - pkts = spnic_rx_fill_wqe(rxq); - if (pkts != rxq->q_depth) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to fill rx wqe\n"); - return -EFAULT; - } - - pkts = spnic_rx_fill_buffers(rxq); - if (!pkts) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to fill Rx buffer\n"); - return -ENOMEM; - } - } - - return 0; -} - -void spnic_free_rxqs(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - kfree(nic_dev->rxqs); -} - -int spnic_alloc_rxqs(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct pci_dev *pdev = nic_dev->pdev; - struct spnic_rxq *rxq = NULL; - u16 num_rxqs = nic_dev->max_qps; - u16 q_id; - u64 rxq_size; - - rxq_size = num_rxqs * sizeof(*nic_dev->rxqs); - if (!rxq_size) { - nic_err(&pdev->dev, "Cannot allocate zero size rxqs\n"); - return -EINVAL; - } - - nic_dev->rxqs = kzalloc(rxq_size, GFP_KERNEL); - if (!nic_dev->rxqs) { - nic_err(&pdev->dev, "Failed to allocate rxqs\n"); - return -ENOMEM; - } - - for (q_id = 0; q_id < num_rxqs; q_id++) { - rxq = &nic_dev->rxqs[q_id]; - rxq->netdev = netdev; - rxq->dev = &pdev->dev; - rxq->q_id = q_id; - rxq->buf_len = nic_dev->rx_buff_len; - rxq->rx_buff_shift = ilog2(nic_dev->rx_buff_len); - rxq->dma_rx_buff_size = nic_dev->dma_rx_buff_size; - rxq->q_depth = nic_dev->q_params.rq_depth; - rxq->q_mask = nic_dev->q_params.rq_depth - 1; - - rxq_stats_init(rxq); - } - - return 0; -} - -int spnic_rx_configure(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - int err; - - if (test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) { - err = spnic_rss_init(nic_dev); - if (err) { - nicif_err(nic_dev, drv, netdev, "Failed to init rss\n"); - return -EFAULT; - } - } - - return 0; -} - -void spnic_rx_remove_configure(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - if (test_bit(SPNIC_RSS_ENABLE, &nic_dev->flags)) - spnic_rss_deinit(nic_dev); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_rx.h b/drivers/net/ethernet/ramaxel/spnic/spnic_rx.h deleted file mode 100644 index 564b5765a41b..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_rx.h +++ /dev/null @@ -1,118 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_RX_H -#define SPNIC_RX_H - -#include <linux/types.h> - -/*rx cqe checksum err*/ -#define SPNIC_RX_CSUM_IP_CSUM_ERR BIT(0) -#define SPNIC_RX_CSUM_TCP_CSUM_ERR BIT(1) -#define SPNIC_RX_CSUM_UDP_CSUM_ERR BIT(2) -#define SPNIC_RX_CSUM_IGMP_CSUM_ERR BIT(3) -#define SPNIC_RX_CSUM_ICMPV4_CSUM_ERR BIT(4) -#define SPNIC_RX_CSUM_ICMPV6_CSUM_ERR BIT(5) -#define SPNIC_RX_CSUM_SCTP_CRC_ERR BIT(6) -#define SPNIC_RX_CSUM_HW_CHECK_NONE BIT(7) -#define SPNIC_RX_CSUM_IPSU_OTHER_ERR BIT(8) - -#define SPNIC_HEADER_DATA_UNIT 2 - -struct spnic_rxq_stats { - u64 packets; - u64 bytes; - u64 errors; - u64 csum_errors; - u64 other_errors; - u64 dropped; - u64 xdp_dropped; - u64 rx_buf_empty; - - u64 alloc_skb_err; - u64 alloc_rx_buf_err; - u64 xdp_large_pkt; - struct u64_stats_sync syncp; -}; - -struct spnic_rx_info { - dma_addr_t buf_dma_addr; - - struct spnic_rq_cqe *cqe; - dma_addr_t cqe_dma; - struct page *page; - u32 page_offset; - struct spnic_rq_wqe *rq_wqe; - struct sk_buff *saved_skb; - u32 skb_len; -}; - -struct spnic_rxq { - struct net_device *netdev; - - u16 q_id; - u32 q_depth; - u32 q_mask; - - u16 buf_len; - u32 rx_buff_shift; - u32 dma_rx_buff_size; - - struct spnic_rxq_stats rxq_stats; - u32 cons_idx; - u32 delta; - - u32 irq_id; - u16 msix_entry_idx; - - struct spnic_rx_info *rx_info; - struct spnic_io_queue *rq; - struct bpf_prog *xdp_prog; - - struct spnic_irq *irq_cfg; - u16 next_to_alloc; - u16 next_to_update; - struct device *dev; /* device for DMA mapping */ - - unsigned long status; - dma_addr_t cqe_start_paddr; - void *cqe_start_vaddr; - - u64 last_moder_packets; - u64 last_moder_bytes; - u8 last_coalesc_timer_cfg; - u8 last_pending_limt; -} ____cacheline_aligned; - -struct spnic_dyna_rxq_res { - u16 next_to_alloc; - struct spnic_rx_info *rx_info; - dma_addr_t cqe_start_paddr; - void *cqe_start_vaddr; -}; - -int spnic_alloc_rxqs(struct net_device *netdev); - -void spnic_free_rxqs(struct net_device *netdev); - -int spnic_alloc_rxqs_res(struct spnic_nic_dev *nic_dev, u16 num_rq, - u32 rq_depth, struct spnic_dyna_rxq_res *rxqs_res); - -void spnic_free_rxqs_res(struct spnic_nic_dev *nic_dev, u16 num_rq, - u32 rq_depth, struct spnic_dyna_rxq_res *rxqs_res); - -int spnic_configure_rxqs(struct spnic_nic_dev *nic_dev, u16 num_rq, - u32 rq_depth, struct spnic_dyna_rxq_res *rxqs_res); - -int spnic_rx_configure(struct net_device *netdev); - -void spnic_rx_remove_configure(struct net_device *netdev); - -int spnic_rx_poll(struct spnic_rxq *rxq, int budget); -int stub_spnic_rx_poll(struct spnic_rxq *rxq, int budget); - -void spnic_rxq_get_stats(struct spnic_rxq *rxq, struct spnic_rxq_stats *stats); - -void spnic_rxq_clean_stats(struct spnic_rxq_stats *rxq_stats); - -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_sriov.c b/drivers/net/ethernet/ramaxel/spnic/spnic_sriov.c deleted file mode 100644 index aac22cb302ea..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_sriov.c +++ /dev/null @@ -1,200 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/pci.h> -#include <linux/interrupt.h> - -#include "sphw_common.h" -#include "sphw_crm.h" -#include "sphw_hw.h" -#include "spnic_lld.h" -#include "spnic_sriov.h" -#include "spnic_dev_mgmt.h" - -int spnic_init_vf_hw(void *hwdev, u16 start_vf_id, u16 end_vf_id) -{ - u16 i, func_idx; - int err; - - /* mbox msg channel resources will be freed during remove process */ - err = sphw_init_func_mbox_msg_channel(hwdev, sphw_func_max_vf(hwdev)); - if (err) - return err; - - /* vf use 256K as default wq page size, and can't change it */ - for (i = start_vf_id; i <= end_vf_id; i++) { - func_idx = sphw_glb_pf_vf_offset(hwdev) + i; - err = sphw_set_wq_page_size(hwdev, func_idx, SPHW_DEFAULT_WQ_PAGE_SIZE, - SPHW_CHANNEL_COMM); - if (err) - return err; - } - - return 0; -} - -int spnic_deinit_vf_hw(void *hwdev, u16 start_vf_id, u16 end_vf_id) -{ - u16 func_idx, idx; - - for (idx = start_vf_id; idx <= end_vf_id; idx++) { - func_idx = sphw_glb_pf_vf_offset(hwdev) + idx; - sphw_set_wq_page_size(hwdev, func_idx, SPHW_HW_WQ_PAGE_SIZE, SPHW_CHANNEL_COMM); - } - - return 0; -} - -int spnic_pci_sriov_disable(struct pci_dev *dev) -{ -#ifdef CONFIG_PCI_IOV - struct spnic_sriov_info *sriov_info = NULL; - struct sphw_event_info event = {0}; - void *hwdev = NULL; - u16 tmp_vfs; - - sriov_info = spnic_get_sriov_info_by_pcidev(dev); - hwdev = spnic_get_hwdev_by_pcidev(dev); - if (!hwdev) { - sdk_err(&dev->dev, "SR-IOV disable is not permitted, please wait...\n"); - return -EPERM; - } - - /* if SR-IOV is already disabled then there is nothing to do */ - if (!sriov_info->sriov_enabled) - return 0; - - if (test_and_set_bit(SPNIC_SRIOV_DISABLE, &sriov_info->state)) { - sdk_err(&dev->dev, "SR-IOV disable in process, please wait"); - return -EPERM; - } - - /* If our VFs are assigned we cannot shut down SR-IOV - * without causing issues, so just leave the hardware - * available but disabled - */ - if (pci_vfs_assigned(dev)) { - clear_bit(SPNIC_SRIOV_DISABLE, &sriov_info->state); - sdk_warn(&dev->dev, "Unloading driver while VFs are assigned - VFs will not be deallocated\n"); - return -EPERM; - } - - event.type = SPHW_EVENT_SRIOV_STATE_CHANGE; - event.sriov_state.enable = 0; - sphw_event_callback(hwdev, &event); - - sriov_info->sriov_enabled = false; - - /* disable iov and allow time for transactions to clear */ - pci_disable_sriov(dev); - - tmp_vfs = (u16)sriov_info->num_vfs; - sriov_info->num_vfs = 0; - spnic_deinit_vf_hw(hwdev, 1, tmp_vfs); - - clear_bit(SPNIC_SRIOV_DISABLE, &sriov_info->state); - -#endif - - return 0; -} - -int spnic_pci_sriov_enable(struct pci_dev *dev, int num_vfs) -{ -#ifdef CONFIG_PCI_IOV - struct spnic_sriov_info *sriov_info = NULL; - struct sphw_event_info event = {0}; - void *hwdev = NULL; - int pre_existing_vfs = 0; - int err = 0; - - sriov_info = spnic_get_sriov_info_by_pcidev(dev); - hwdev = spnic_get_hwdev_by_pcidev(dev); - if (!hwdev) { - sdk_err(&dev->dev, "SR-IOV enable is not permitted, please wait...\n"); - return -EPERM; - } - - if (test_and_set_bit(SPNIC_SRIOV_ENABLE, &sriov_info->state)) { - sdk_err(&dev->dev, "SR-IOV enable in process, please wait, num_vfs %d\n", - num_vfs); - return -EPERM; - } - - pre_existing_vfs = pci_num_vf(dev); - - if (num_vfs > pci_sriov_get_totalvfs(dev)) { - clear_bit(SPNIC_SRIOV_ENABLE, &sriov_info->state); - return -ERANGE; - } - if (pre_existing_vfs && pre_existing_vfs != num_vfs) { - err = spnic_pci_sriov_disable(dev); - if (err) { - clear_bit(SPNIC_SRIOV_ENABLE, &sriov_info->state); - return err; - } - } else if (pre_existing_vfs == num_vfs) { - clear_bit(SPNIC_SRIOV_ENABLE, &sriov_info->state); - return num_vfs; - } - - err = spnic_init_vf_hw(hwdev, 1, (u16)num_vfs); - if (err) { - sdk_err(&dev->dev, "Failed to init vf in hardware before enable sriov, error %d\n", - err); - clear_bit(SPNIC_SRIOV_ENABLE, &sriov_info->state); - return err; - } - - err = pci_enable_sriov(dev, num_vfs); - if (err) { - sdk_err(&dev->dev, "Failed to enable SR-IOV, error %d\n", err); - clear_bit(SPNIC_SRIOV_ENABLE, &sriov_info->state); - return err; - } - - sriov_info->sriov_enabled = true; - sriov_info->num_vfs = num_vfs; - - event.type = SPHW_EVENT_SRIOV_STATE_CHANGE; - event.sriov_state.enable = 1; - event.sriov_state.num_vfs = (u16)num_vfs; - sphw_event_callback(hwdev, &event); - - clear_bit(SPNIC_SRIOV_ENABLE, &sriov_info->state); - - return num_vfs; -#else - - return 0; -#endif -} - -static bool spnic_is_support_sriov_configure(struct pci_dev *pdev) -{ - /* TODO: get cap from firmware */ - - return true; -} - -int spnic_pci_sriov_configure(struct pci_dev *dev, int num_vfs) -{ - struct spnic_sriov_info *sriov_info = NULL; - - if (!spnic_is_support_sriov_configure(dev)) - return -EFAULT; - - sriov_info = spnic_get_sriov_info_by_pcidev(dev); - if (!sriov_info) - return -EFAULT; - - if (!test_bit(SPNIC_FUNC_PERSENT, &sriov_info->state)) - return -EFAULT; - - if (!num_vfs) - return spnic_pci_sriov_disable(dev); - else - return spnic_pci_sriov_enable(dev, num_vfs); -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_sriov.h b/drivers/net/ethernet/ramaxel/spnic/spnic_sriov.h deleted file mode 100644 index 622845e30427..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_sriov.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_SRIOV_H -#define SPNIC_SRIOV_H -#include <linux/types.h> - -enum spnic_sriov_state { - SPNIC_SRIOV_DISABLE, - SPNIC_SRIOV_ENABLE, - SPNIC_FUNC_PERSENT, -}; - -struct spnic_sriov_info { - bool sriov_enabled; - unsigned int num_vfs; - unsigned long state; -}; - -struct spnic_sriov_info *spnic_get_sriov_info_by_pcidev(struct pci_dev *pdev); -int spnic_pci_sriov_disable(struct pci_dev *dev); -int spnic_pci_sriov_enable(struct pci_dev *dev, int num_vfs); -int spnic_pci_sriov_configure(struct pci_dev *dev, int num_vfs); -#endif diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_tx.c b/drivers/net/ethernet/ramaxel/spnic/spnic_tx.c deleted file mode 100644 index 7478e76aa729..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_tx.c +++ /dev/null @@ -1,877 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": [NIC]" fmt - -#include <linux/netdevice.h> -#include <linux/kernel.h> -#include <linux/skbuff.h> -#include <linux/interrupt.h> -#include <linux/device.h> -#include <linux/pci.h> -#include <linux/tcp.h> -#include <linux/sctp.h> -#include <net/xfrm.h> -#include <linux/dma-mapping.h> -#include <linux/types.h> -#include <linux/u64_stats_sync.h> -#include <linux/module.h> -#include <linux/vmalloc.h> - -#include "sphw_crm.h" -#include "spnic_nic_qp.h" -#include "spnic_nic_io.h" -#include "spnic_nic_cfg.h" -#include "spnic_nic_dev.h" -#include "spnic_tx.h" - -#define MIN_SKB_LEN 32 - -#define MAX_PAYLOAD_OFFSET 221 - -#define NIC_QID(q_id, nic_dev) ((q_id) & ((nic_dev)->num_qps - 1)) - -#define SPNIC_TX_TASK_WRAPPED 1 -#define SPNIC_TX_BD_DESC_WRAPPED 2 - -#define TXQ_STATS_INC(txq, field) \ -do { \ - u64_stats_update_begin(&(txq)->txq_stats.syncp); \ - (txq)->txq_stats.field++; \ - u64_stats_update_end(&(txq)->txq_stats.syncp); \ -} while (0) - -void spnic_txq_get_stats(struct spnic_txq *txq, struct spnic_txq_stats *stats) -{ - struct spnic_txq_stats *txq_stats = &txq->txq_stats; - unsigned int start; - - u64_stats_update_begin(&stats->syncp); - do { - start = u64_stats_fetch_begin(&txq_stats->syncp); - stats->bytes = txq_stats->bytes; - stats->packets = txq_stats->packets; - stats->busy = txq_stats->busy; - stats->wake = txq_stats->wake; - stats->dropped = txq_stats->dropped; - } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); - u64_stats_update_end(&stats->syncp); -} - -void spnic_txq_clean_stats(struct spnic_txq_stats *txq_stats) -{ - u64_stats_update_begin(&txq_stats->syncp); - txq_stats->bytes = 0; - txq_stats->packets = 0; - txq_stats->busy = 0; - txq_stats->wake = 0; - txq_stats->dropped = 0; - - txq_stats->skb_pad_err = 0; - txq_stats->frag_len_overflow = 0; - txq_stats->offload_cow_skb_err = 0; - txq_stats->map_frag_err = 0; - txq_stats->unknown_tunnel_pkt = 0; - txq_stats->frag_size_err = 0; - u64_stats_update_end(&txq_stats->syncp); -} - -static void txq_stats_init(struct spnic_txq *txq) -{ - struct spnic_txq_stats *txq_stats = &txq->txq_stats; - - u64_stats_init(&txq_stats->syncp); - spnic_txq_clean_stats(txq_stats); -} - -static inline void spnic_set_buf_desc(struct spnic_sq_bufdesc *buf_descs, dma_addr_t addr, u32 len) -{ - buf_descs->hi_addr = upper_32_bits(addr); - buf_descs->lo_addr = lower_32_bits(addr); - buf_descs->len = len; -} - -static int tx_map_skb(struct spnic_nic_dev *nic_dev, struct sk_buff *skb, - u16 valid_nr_frags, struct spnic_txq *txq, - struct spnic_tx_info *tx_info, - struct spnic_sq_wqe_combo *wqe_combo) -{ - struct spnic_sq_wqe_desc *wqe_desc = wqe_combo->ctrl_bd0; - struct spnic_sq_bufdesc *buf_desc = wqe_combo->bds_head; - struct spnic_dma_info *dma_info = tx_info->dma_info; - struct pci_dev *pdev = nic_dev->pdev; - skb_frag_t *frag = NULL; - u32 j, i; - int err; - - dma_info[0].dma = dma_map_single(&pdev->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); - if (dma_mapping_error(&pdev->dev, dma_info[0].dma)) { - TXQ_STATS_INC(txq, map_frag_err); - return -EFAULT; - } - - dma_info[0].len = skb_headlen(skb); - - wqe_desc->hi_addr = upper_32_bits(dma_info[0].dma); - wqe_desc->lo_addr = lower_32_bits(dma_info[0].dma); - - wqe_desc->ctrl_len = dma_info[0].len; - - for (i = 0; i < valid_nr_frags;) { - frag = &(skb_shinfo(skb)->frags[i]); - if (unlikely(i == wqe_combo->first_bds_num)) - buf_desc = wqe_combo->bds_sec2; - - i++; - dma_info[i].dma = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag), - DMA_TO_DEVICE); - if (dma_mapping_error(&pdev->dev, dma_info[i].dma)) { - TXQ_STATS_INC(txq, map_frag_err); - i--; - err = -EFAULT; - goto frag_map_err; - } - dma_info[i].len = skb_frag_size(frag); - - spnic_set_buf_desc(buf_desc, dma_info[i].dma, dma_info[i].len); - buf_desc++; - } - - return 0; - -frag_map_err: - for (j = 0; j < i;) { - j++; - dma_unmap_page(&pdev->dev, dma_info[j].dma, - dma_info[j].len, DMA_TO_DEVICE); - } - dma_unmap_single(&pdev->dev, dma_info[0].dma, dma_info[0].len, DMA_TO_DEVICE); - return err; -} - -static inline void tx_unmap_skb(struct spnic_nic_dev *nic_dev, - struct sk_buff *skb, u16 valid_nr_frags, - struct spnic_dma_info *dma_info) -{ - struct pci_dev *pdev = nic_dev->pdev; - int i; - - for (i = 0; i < valid_nr_frags; ) { - i++; - dma_unmap_page(&pdev->dev, dma_info[i].dma, dma_info[i].len, DMA_TO_DEVICE); - } - - dma_unmap_single(&pdev->dev, dma_info[0].dma, dma_info[0].len, DMA_TO_DEVICE); -} - -union spnic_l4 { - struct tcphdr *tcp; - struct udphdr *udp; - unsigned char *hdr; -}; - -enum sq_l3_type { - UNKNOWN_L3TYPE = 0, - IPV6_PKT = 1, - IPV4_PKT_NO_CHKSUM_OFFLOAD = 2, - IPV4_PKT_WITH_CHKSUM_OFFLOAD = 3, -}; - -enum sq_l4offload_type { - OFFLOAD_DISABLE = 0, - TCP_OFFLOAD_ENABLE = 1, - SCTP_OFFLOAD_ENABLE = 2, - UDP_OFFLOAD_ENABLE = 3, -}; - -/*initialize l4_len and offset*/ -static inline void get_inner_l4_info(struct sk_buff *skb, union spnic_l4 *l4, - u8 l4_proto, u32 *offset, - enum sq_l4offload_type *l4_offload) -{ - switch (l4_proto) { - case IPPROTO_TCP: - *l4_offload = TCP_OFFLOAD_ENABLE; - /* To keep same with TSO, payload offset begins from paylaod */ - *offset = (l4->tcp->doff << 2) + TRANSPORT_OFFSET(l4->hdr, skb); - break; - - case IPPROTO_UDP: - *l4_offload = UDP_OFFLOAD_ENABLE; - *offset = TRANSPORT_OFFSET(l4->hdr, skb); - break; - default: - break; - } -} - -static int spnic_tx_csum(struct spnic_txq *txq, struct spnic_sq_task *task, struct sk_buff *skb) -{ - if (skb->ip_summed != CHECKSUM_PARTIAL) - return 0; - - if (skb->encapsulation) { - union spnic_ip ip; - u8 l4_proto; - - task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, TUNNEL_FLAG); - - ip.hdr = skb_network_header(skb); - if (ip.v4->version == IPV4_VERSION) { - l4_proto = ip.v4->protocol; - } else if (ip.v4->version == IPV6_VERSION) { - union spnic_l4 l4; - unsigned char *exthdr; - __be16 frag_off; - - exthdr = ip.hdr + sizeof(*ip.v6); - l4_proto = ip.v6->nexthdr; - l4.hdr = skb_transport_header(skb); - if (l4.hdr != exthdr) - ipv6_skip_exthdr(skb, exthdr - skb->data, &l4_proto, &frag_off); - } else { - l4_proto = IPPROTO_RAW; - } - - if (l4_proto != IPPROTO_UDP || - ((struct udphdr *)skb_transport_header(skb))->dest != VXLAN_OFFLOAD_PORT_BE) { - TXQ_STATS_INC(txq, unknown_tunnel_pkt); - /* Unsupport tunnel packet, disable csum offload */ - skb_checksum_help(skb); - return 0; - } - } - - task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, INNER_L4_EN); - - return 1; -} - -static void get_inner_l3_l4_type(struct sk_buff *skb, union spnic_ip *ip, - union spnic_l4 *l4, enum sq_l3_type *l3_type, u8 *l4_proto) -{ - unsigned char *exthdr = NULL; - - if (ip->v4->version == 4) { - *l3_type = IPV4_PKT_WITH_CHKSUM_OFFLOAD; - *l4_proto = ip->v4->protocol; - - } else if (ip->v4->version == 6) { - *l3_type = IPV6_PKT; - exthdr = ip->hdr + sizeof(*ip->v6); - *l4_proto = ip->v6->nexthdr; - if (exthdr != l4->hdr) { - __be16 frag_off = 0; - - ipv6_skip_exthdr(skb, (int)(exthdr - skb->data), l4_proto, &frag_off); - } - } else { - *l3_type = UNKNOWN_L3TYPE; - *l4_proto = 0; - } -} - -static inline void spnic_set_tso_info(struct spnic_sq_task *task, u32 *queue_info, - enum sq_l4offload_type l4_offload, u32 offset, u32 mss) -{ - if (l4_offload == TCP_OFFLOAD_ENABLE) { - *queue_info |= SQ_CTRL_QUEUE_INFO_SET(1U, TSO); - task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, INNER_L4_EN); - } else if (l4_offload == UDP_OFFLOAD_ENABLE) { - *queue_info |= SQ_CTRL_QUEUE_INFO_SET(1U, UFO); - task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, INNER_L4_EN); - } - - /*Default enable L3 calculation*/ - task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, INNER_L3_EN); - - *queue_info |= SQ_CTRL_QUEUE_INFO_SET(offset >> 1, PLDOFF); - - /* set MSS value */ - *queue_info = SQ_CTRL_QUEUE_INFO_CLEAR(*queue_info, MSS); - *queue_info |= SQ_CTRL_QUEUE_INFO_SET(mss, MSS); -} - -static int spnic_tso(struct spnic_sq_task *task, u32 *queue_info, struct sk_buff *skb) -{ - enum sq_l4offload_type l4_offload = OFFLOAD_DISABLE; - enum sq_l3_type l3_type; - union spnic_ip ip; - union spnic_l4 l4; - u32 offset = 0; - u8 l4_proto; - int err; - - if (!skb_is_gso(skb)) - return 0; - - err = skb_cow_head(skb, 0); - if (err < 0) - return err; - - if (skb->encapsulation) { - u32 gso_type = skb_shinfo(skb)->gso_type; - /* L3 checksum always enable */ - task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, OUT_L3_EN); - task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, TUNNEL_FLAG); - - l4.hdr = skb_transport_header(skb); - ip.hdr = skb_network_header(skb); - - if (gso_type & SKB_GSO_UDP_TUNNEL_CSUM) { - l4.udp->check = ~csum_magic(&ip, IPPROTO_UDP); - task->pkt_info0 |= SQ_TASK_INFO0_SET(1U, OUT_L4_EN); - } else if (gso_type & SKB_GSO_UDP_TUNNEL) { - } - - ip.hdr = skb_inner_network_header(skb); - l4.hdr = skb_inner_transport_header(skb); - } else { - ip.hdr = skb_network_header(skb); - l4.hdr = skb_transport_header(skb); - } - - get_inner_l3_l4_type(skb, &ip, &l4, &l3_type, &l4_proto); - - if (l4_proto == IPPROTO_TCP) - l4.tcp->check = ~csum_magic(&ip, IPPROTO_TCP); - - get_inner_l4_info(skb, &l4, l4_proto, &offset, &l4_offload); - - spnic_set_tso_info(task, queue_info, l4_offload, offset, skb_shinfo(skb)->gso_size); - - return 1; -} - -static u32 spnic_tx_offload(struct sk_buff *skb, struct spnic_sq_task *task, - u32 *queue_info, struct spnic_txq *txq) -{ - u32 offload = 0; - int tso_cs_en; - - task->pkt_info0 = 0; - task->ip_identify = 0; - task->pkt_info2 = 0; - task->vlan_offload = 0; - - tso_cs_en = spnic_tso(task, queue_info, skb); - if (tso_cs_en < 0) { - offload = TX_OFFLOAD_INVALID; - return offload; - } else if (tso_cs_en) { - offload |= TX_OFFLOAD_TSO; - } else { - tso_cs_en = spnic_tx_csum(txq, task, skb); - if (tso_cs_en) - offload |= TX_OFFLOAD_CSUM; - } - -#define VLAN_INSERT_MODE_MAX 5 - if (unlikely(skb_vlan_tag_present(skb))) { - /* select vlan insert mode by qid, default 802.1Q Tag type*/ - spnic_set_vlan_tx_offload(task, skb_vlan_tag_get(skb), - txq->q_id % VLAN_INSERT_MODE_MAX); - offload |= TX_OFFLOAD_VLAN; - } - - if (unlikely(SQ_CTRL_QUEUE_INFO_GET(*queue_info, PLDOFF) > MAX_PAYLOAD_OFFSET)) { - offload = TX_OFFLOAD_INVALID; - return offload; - } - - return offload; -} - -static inline void get_pkt_stats(struct spnic_tx_info *tx_info, struct sk_buff *skb) -{ - u32 ihs, hdr_len; - - if (skb_is_gso(skb)) { - if (skb->encapsulation) - ihs = skb_inner_transport_offset(skb) + inner_tcp_hdrlen(skb); - else - ihs = skb_transport_offset(skb) + tcp_hdrlen(skb); - - hdr_len = (skb_shinfo(skb)->gso_segs - 1) * ihs; - tx_info->num_bytes = skb->len + (u64)hdr_len; - - } else { - tx_info->num_bytes = skb->len > ETH_ZLEN ? skb->len : ETH_ZLEN; - } - - tx_info->num_pkts = 1; -} - -static inline int spnic_maybe_stop_tx(struct spnic_txq *txq, u16 wqebb_cnt) -{ - if (likely(spnic_get_sq_free_wqebbs(txq->sq) >= wqebb_cnt)) - return 0; - - /* We need to check again in a case another CPU has just - * made room available. - */ - netif_stop_subqueue(txq->netdev, txq->q_id); - - if (likely(spnic_get_sq_free_wqebbs(txq->sq) < wqebb_cnt)) - return -EBUSY; - - /* there have enough wqebbs after queue is wake up */ - netif_start_subqueue(txq->netdev, txq->q_id); - - return 0; -} - -static inline u16 spnic_set_wqe_combo(struct spnic_txq *txq, struct spnic_sq_wqe_combo *wqe_combo, - u32 offload, u16 num_sge, u16 *curr_pi) -{ - void *second_part_wqebbs_addr = NULL; - void *wqe = NULL; - u16 first_part_wqebbs_num, tmp_pi; - - wqe_combo->ctrl_bd0 = spnic_get_sq_one_wqebb(txq->sq, curr_pi); - if (!offload && num_sge == 1) { - wqe_combo->wqe_type = SQ_WQE_COMPACT_TYPE; - return spnic_get_and_update_sq_owner(txq->sq, *curr_pi, 1); - } - - wqe_combo->wqe_type = SQ_WQE_EXTENDED_TYPE; - - if (offload) { - wqe_combo->task = spnic_get_sq_one_wqebb(txq->sq, &tmp_pi); - wqe_combo->task_type = SQ_WQE_TASKSECT_16BYTES; - } else { - wqe_combo->task_type = SQ_WQE_TASKSECT_46BITS; - } - - if (num_sge > 1) { - /* first wqebb contain bd0, and bd size is equal to sq wqebb - * size, so we use (num_sge - 1) as wanted weqbb_cnt - */ - wqe = spnic_get_sq_multi_wqebbs(txq->sq, num_sge - 1, &tmp_pi, - &second_part_wqebbs_addr, - &first_part_wqebbs_num); - wqe_combo->bds_head = wqe; - wqe_combo->bds_sec2 = second_part_wqebbs_addr; - wqe_combo->first_bds_num = first_part_wqebbs_num; - } - - return spnic_get_and_update_sq_owner(txq->sq, *curr_pi, num_sge + (u16)!!offload); -} - -inline u8 spnic_get_vlan_pri(struct sk_buff *skb) -{ - u16 vlan_tci = 0; - int err; - - err = vlan_get_tag(skb, &vlan_tci); - if (err) - return 0; - - return (vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; -} - -static netdev_tx_t spnic_send_one_skb(struct sk_buff *skb, struct net_device *netdev, - struct spnic_txq *txq) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_sq_wqe_combo wqe_combo = {0}; - struct spnic_tx_info *tx_info = NULL; - struct spnic_sq_task task; - u32 offload, queue_info = 0; - u16 owner = 0, pi = 0; - u16 wqebb_cnt, num_sge, valid_nr_frags; - bool find_zero_sge_len = false; - int err, i; - - if (unlikely(skb->len < MIN_SKB_LEN)) { - if (skb_pad(skb, (int)(MIN_SKB_LEN - skb->len))) { - TXQ_STATS_INC(txq, skb_pad_err); - goto tx_skb_pad_err; - } - - skb->len = MIN_SKB_LEN; - } - - valid_nr_frags = 0; - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - if (!skb_frag_size(&skb_shinfo(skb)->frags[i])) { - find_zero_sge_len = true; - continue; - } else if (find_zero_sge_len) { - TXQ_STATS_INC(txq, frag_size_err); - goto tx_drop_pkts; - } - - valid_nr_frags++; - } - - num_sge = valid_nr_frags + 1; - - /* assume need normal TS format wqe, task info need 1 wqebb */ - wqebb_cnt = num_sge + 1; - if (unlikely(spnic_maybe_stop_tx(txq, wqebb_cnt))) { - TXQ_STATS_INC(txq, busy); - return NETDEV_TX_BUSY; - } - - offload = spnic_tx_offload(skb, &task, &queue_info, txq); - if (unlikely(offload == TX_OFFLOAD_INVALID)) { - TXQ_STATS_INC(txq, offload_cow_skb_err); - goto tx_drop_pkts; - } else if (!offload) { - /* no TS in current wqe */ - wqebb_cnt -= 1; - } - - owner = spnic_set_wqe_combo(txq, &wqe_combo, offload, num_sge, &pi); - if (offload) { - wqe_combo.task->ip_identify = task.ip_identify; - wqe_combo.task->pkt_info0 = task.pkt_info0; - wqe_combo.task->pkt_info2 = task.pkt_info2; - wqe_combo.task->vlan_offload = task.vlan_offload; - } - - tx_info = &txq->tx_info[pi]; - tx_info->skb = skb; - tx_info->wqebb_cnt = wqebb_cnt; - tx_info->valid_nr_frags = valid_nr_frags; - - err = tx_map_skb(nic_dev, skb, valid_nr_frags, txq, tx_info, &wqe_combo); - if (err) { - spnic_rollback_sq_wqebbs(txq->sq, wqebb_cnt, owner); - goto tx_drop_pkts; - } - - get_pkt_stats(tx_info, skb); - - spnic_prepare_sq_ctrl(&wqe_combo, queue_info, num_sge, owner); - - spnic_write_db(txq->sq, txq->cos, SQ_CFLAG_DP, spnic_get_sq_local_pi(txq->sq)); - - return NETDEV_TX_OK; - -tx_drop_pkts: - dev_kfree_skb_any(skb); - -tx_skb_pad_err: - TXQ_STATS_INC(txq, dropped); - - return NETDEV_TX_OK; -} - -netdev_tx_t spnic_lb_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u16 q_id = skb_get_queue_mapping(skb); - struct spnic_txq *txq = &nic_dev->txqs[q_id]; - - return spnic_send_one_skb(skb, netdev, txq); -} - -netdev_tx_t spnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct spnic_txq *txq = NULL; - u16 q_id = skb_get_queue_mapping(skb); - - if (unlikely(!netif_carrier_ok(netdev))) { - dev_kfree_skb_any(skb); - SPNIC_NIC_STATS_INC(nic_dev, tx_carrier_off_drop); - return NETDEV_TX_OK; - } - - if (unlikely(q_id >= nic_dev->q_params.num_qps)) { - txq = &nic_dev->txqs[0]; - SPNIC_NIC_STATS_INC(nic_dev, tx_invalid_qid); - goto tx_drop_pkts; - } - txq = &nic_dev->txqs[q_id]; - - return spnic_send_one_skb(skb, netdev, txq); - -tx_drop_pkts: - dev_kfree_skb_any(skb); - u64_stats_update_begin(&txq->txq_stats.syncp); - txq->txq_stats.dropped++; - u64_stats_update_end(&txq->txq_stats.syncp); - - return NETDEV_TX_OK; -} - -static inline void tx_free_skb(struct spnic_nic_dev *nic_dev, struct spnic_tx_info *tx_info) -{ - tx_unmap_skb(nic_dev, tx_info->skb, tx_info->valid_nr_frags, - tx_info->dma_info); - dev_kfree_skb_any(tx_info->skb); - tx_info->skb = NULL; -} - -static void free_all_tx_skbs(struct spnic_nic_dev *nic_dev, u32 sq_depth, - struct spnic_tx_info *tx_info_arr) -{ - struct spnic_tx_info *tx_info = NULL; - u32 idx; - - for (idx = 0; idx < sq_depth; idx++) { - tx_info = &tx_info_arr[idx]; - if (tx_info->skb) - tx_free_skb(nic_dev, tx_info); - } -} - -int spnic_tx_poll(struct spnic_txq *txq, int budget) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(txq->netdev); - struct spnic_tx_info *tx_info = NULL; - u64 tx_bytes = 0, wake = 0; - int pkts = 0, nr_pkts = 0; - u16 wqebb_cnt = 0; - u16 hw_ci, sw_ci = 0, q_id = txq->sq->q_id; - - hw_ci = spnic_get_sq_hw_ci(txq->sq); - dma_rmb(); - sw_ci = spnic_get_sq_local_ci(txq->sq); - - do { - tx_info = &txq->tx_info[sw_ci]; - - /* Whether all of the wqebb of this wqe is completed */ - if (hw_ci == sw_ci || - ((hw_ci - sw_ci) & txq->q_mask) < tx_info->wqebb_cnt) - break; - - sw_ci = (u16)(sw_ci + tx_info->wqebb_cnt) & txq->q_mask; - prefetch(&txq->tx_info[sw_ci]); - - wqebb_cnt += tx_info->wqebb_cnt; - - tx_bytes += tx_info->num_bytes; - nr_pkts += tx_info->num_pkts; - pkts++; - - tx_free_skb(nic_dev, tx_info); - - } while (likely(pkts < budget)); - - spnic_update_sq_local_ci(txq->sq, wqebb_cnt); - - if (unlikely(__netif_subqueue_stopped(nic_dev->netdev, q_id) && - spnic_get_sq_free_wqebbs(txq->sq) >= 1 && - test_bit(SPNIC_INTF_UP, &nic_dev->flags))) { - struct netdev_queue *netdev_txq = netdev_get_tx_queue(txq->netdev, q_id); - - __netif_tx_lock(netdev_txq, smp_processor_id()); - /* To avoid re-waking subqueue with xmit_frame */ - if (__netif_subqueue_stopped(nic_dev->netdev, q_id)) { - netif_wake_subqueue(nic_dev->netdev, q_id); - wake++; - } - __netif_tx_unlock(netdev_txq); - } - - u64_stats_update_begin(&txq->txq_stats.syncp); - txq->txq_stats.bytes += tx_bytes; - txq->txq_stats.packets += nr_pkts; - txq->txq_stats.wake += wake; - u64_stats_update_end(&txq->txq_stats.syncp); - - return pkts; -} - -void spnic_set_txq_cos(struct spnic_nic_dev *nic_dev, u16 start_qid, u16 q_num, u8 cos) -{ - u16 idx; - - for (idx = 0; idx < q_num; idx++) - nic_dev->txqs[idx + start_qid].cos = cos; -} - -#define SPNIC_BDS_PER_SQ_WQEBB \ - (SPNIC_SQ_WQEBB_SIZE / sizeof(struct spnic_sq_bufdesc)) - -int spnic_alloc_txqs_res(struct spnic_nic_dev *nic_dev, u16 num_sq, - u32 sq_depth, struct spnic_dyna_txq_res *txqs_res) -{ - struct spnic_dyna_txq_res *tqres = NULL; - int idx, i; - u64 size; - - for (idx = 0; idx < num_sq; idx++) { - tqres = &txqs_res[idx]; - - size = sizeof(*tqres->tx_info) * sq_depth; - tqres->tx_info = kzalloc(size, GFP_KERNEL); - if (!tqres->tx_info) { - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to alloc txq%d tx info\n", idx); - goto err_out; - } - - size = sizeof(*tqres->bds) * (sq_depth * SPNIC_BDS_PER_SQ_WQEBB + SPNIC_MAX_SQ_SGE); - tqres->bds = kzalloc(size, GFP_KERNEL); - if (!tqres->bds) { - kfree(tqres->tx_info); - nicif_err(nic_dev, drv, nic_dev->netdev, - "Failed to alloc txq%d bds info\n", idx); - goto err_out; - } - } - - return 0; - -err_out: - for (i = 0; i < idx; i++) { - tqres = &txqs_res[i]; - - kfree(tqres->bds); - kfree(tqres->tx_info); - } - - return -ENOMEM; -} - -void spnic_free_txqs_res(struct spnic_nic_dev *nic_dev, u16 num_sq, - u32 sq_depth, struct spnic_dyna_txq_res *txqs_res) -{ - struct spnic_dyna_txq_res *tqres = NULL; - int idx; - - for (idx = 0; idx < num_sq; idx++) { - tqres = &txqs_res[idx]; - - free_all_tx_skbs(nic_dev, sq_depth, tqres->tx_info); - kfree(tqres->bds); - kfree(tqres->tx_info); - } -} - -int spnic_configure_txqs(struct spnic_nic_dev *nic_dev, u16 num_sq, - u32 sq_depth, struct spnic_dyna_txq_res *txqs_res) -{ - struct spnic_dyna_txq_res *tqres = NULL; - struct spnic_txq *txq = NULL; - u16 q_id; - u32 idx; - - for (q_id = 0; q_id < num_sq; q_id++) { - txq = &nic_dev->txqs[q_id]; - tqres = &txqs_res[q_id]; - - txq->q_depth = sq_depth; - txq->q_mask = sq_depth - 1; - - txq->tx_info = tqres->tx_info; - for (idx = 0; idx < sq_depth; idx++) - txq->tx_info[idx].dma_info = &tqres->bds[idx * SPNIC_BDS_PER_SQ_WQEBB]; - - txq->sq = spnic_get_nic_queue(nic_dev->hwdev, q_id, SPNIC_SQ); - if (!txq->sq) { - nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to get %u sq\n", q_id); - return -EFAULT; - } - } - - return 0; -} - -int spnic_alloc_txqs(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - struct pci_dev *pdev = nic_dev->pdev; - struct spnic_txq *txq = NULL; - u16 q_id, num_txqs = nic_dev->max_qps; - u64 txq_size; - - txq_size = num_txqs * sizeof(*nic_dev->txqs); - if (!txq_size) { - nic_err(&pdev->dev, "Cannot allocate zero size txqs\n"); - return -EINVAL; - } - - nic_dev->txqs = kzalloc(txq_size, GFP_KERNEL); - if (!nic_dev->txqs) { - nic_err(&pdev->dev, "Failed to allocate txqs\n"); - return -ENOMEM; - } - - for (q_id = 0; q_id < num_txqs; q_id++) { - txq = &nic_dev->txqs[q_id]; - txq->netdev = netdev; - txq->q_id = q_id; - txq->q_depth = nic_dev->q_params.sq_depth; - txq->q_mask = nic_dev->q_params.sq_depth - 1; - txq->dev = &pdev->dev; - - txq_stats_init(txq); - } - - return 0; -} - -void spnic_free_txqs(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - - kfree(nic_dev->txqs); -} - -static bool is_hw_complete_sq_process(struct spnic_io_queue *sq) -{ - u16 sw_pi, hw_ci; - - sw_pi = spnic_get_sq_local_pi(sq); - hw_ci = spnic_get_sq_hw_ci(sq); - - return sw_pi == hw_ci; -} - -#define SPNIC_FLUSH_QUEUE_TIMEOUT 1000 -static int spnic_stop_sq(struct spnic_txq *txq) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(txq->netdev); - unsigned long timeout; - int err; - - timeout = msecs_to_jiffies(SPNIC_FLUSH_QUEUE_TIMEOUT) + jiffies; - do { - if (is_hw_complete_sq_process(txq->sq)) - return 0; - - usleep_range(900, 1000); - } while (time_before(jiffies, timeout)); - - /* force hardware to drop packets */ - timeout = msecs_to_jiffies(SPNIC_FLUSH_QUEUE_TIMEOUT) + jiffies; - do { - if (is_hw_complete_sq_process(txq->sq)) - return 0; - - err = spnic_force_drop_tx_pkt(nic_dev->hwdev); - if (err) - break; - - usleep_range(9900, 10000); - } while (time_before(jiffies, timeout)); - - /* Avoid msleep takes too long and get a fake result */ - if (is_hw_complete_sq_process(txq->sq)) - return 0; - - return -EFAULT; -} - -/* should stop transmit any packets before calling this function */ -int spnic_flush_txqs(struct net_device *netdev) -{ - struct spnic_nic_dev *nic_dev = netdev_priv(netdev); - u16 qid; - int err; - - for (qid = 0; qid < nic_dev->q_params.num_qps; qid++) { - err = spnic_stop_sq(&nic_dev->txqs[qid]); - if (err) - nicif_err(nic_dev, drv, netdev, "Failed to stop sq%u\n", qid); - } - - return 0; -} diff --git a/drivers/net/ethernet/ramaxel/spnic/spnic_tx.h b/drivers/net/ethernet/ramaxel/spnic/spnic_tx.h deleted file mode 100644 index c3109db83299..000000000000 --- a/drivers/net/ethernet/ramaxel/spnic/spnic_tx.h +++ /dev/null @@ -1,129 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */ - -#ifndef SPNIC_TX_H -#define SPNIC_TX_H - -#include <linux/ip.h> -#include <linux/ipv6.h> -#include <net/ipv6.h> -#include <net/checksum.h> -#include <net/ip6_checksum.h> - -#include "spnic_nic_qp.h" - -#define VXLAN_OFFLOAD_PORT_BE htons(4789) - -enum tx_offload_type { - TX_OFFLOAD_TSO = BIT(0), - TX_OFFLOAD_CSUM = BIT(1), - TX_OFFLOAD_VLAN = BIT(2), - TX_OFFLOAD_INVALID = BIT(3), - TX_OFFLOAD_ESP = BIT(4), -}; - -struct spnic_txq_stats { - u64 packets; - u64 bytes; - u64 busy; - u64 wake; - u64 dropped; - - /* Subdivision statistics show in private tool */ - u64 skb_pad_err; - u64 frag_len_overflow; - u64 offload_cow_skb_err; - u64 map_frag_err; - u64 unknown_tunnel_pkt; - u64 frag_size_err; - - struct u64_stats_sync syncp; -}; - -struct spnic_dma_info { - dma_addr_t dma; - u32 len; -}; - -#define IPV4_VERSION 4 -#define IPV6_VERSION 6 -#define TCP_HDR_DOFF_UNIT 2 -#define TRANSPORT_OFFSET(l4_hdr, skb) ((u32)((l4_hdr) - (skb)->data)) - -union spnic_ip { - struct iphdr *v4; - struct ipv6hdr *v6; - unsigned char *hdr; -}; - -struct spnic_tx_info { - struct sk_buff *skb; - - u16 wqebb_cnt; - u16 valid_nr_frags; - - int num_sge; - u16 num_pkts; - u64 num_bytes; - struct spnic_dma_info *dma_info; -}; - -struct spnic_txq { - struct net_device *netdev; - struct device *dev; - - struct spnic_txq_stats txq_stats; - - u8 cos; - u16 q_id; - u32 q_mask; - u32 q_depth; - - struct spnic_tx_info *tx_info; - struct spnic_io_queue *sq; - - u64 last_moder_packets; - u64 last_moder_bytes; -} ____cacheline_aligned; - -netdev_tx_t spnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev); - -netdev_tx_t spnic_lb_xmit_frame(struct sk_buff *skb, struct net_device *netdev); - -struct spnic_dyna_txq_res { - struct spnic_tx_info *tx_info; - struct spnic_dma_info *bds; -}; - -void spnic_txq_get_stats(struct spnic_txq *txq, struct spnic_txq_stats *stats); - -void spnic_txq_clean_stats(struct spnic_txq_stats *txq_stats); - -struct spnic_nic_dev; -int spnic_alloc_txqs_res(struct spnic_nic_dev *nic_dev, u16 num_sq, - u32 sq_depth, struct spnic_dyna_txq_res *txqs_res); - -void spnic_free_txqs_res(struct spnic_nic_dev *nic_dev, u16 num_sq, - u32 sq_depth, struct spnic_dyna_txq_res *txqs_res); - -int spnic_configure_txqs(struct spnic_nic_dev *nic_dev, u16 num_sq, - u32 sq_depth, struct spnic_dyna_txq_res *txqs_res); - -int spnic_alloc_txqs(struct net_device *netdev); - -void spnic_free_txqs(struct net_device *netdev); - -int spnic_tx_poll(struct spnic_txq *txq, int budget); - -int spnic_flush_txqs(struct net_device *netdev); - -void spnic_set_txq_cos(struct spnic_nic_dev *nic_dev, u16 start_qid, u16 q_num, u8 cos); - -static inline __sum16 csum_magic(union spnic_ip *ip, unsigned short proto) -{ - return (ip->v4->version == IPV4_VERSION) ? - csum_tcpudp_magic(ip->v4->saddr, ip->v4->daddr, 0, proto, 0) : - csum_ipv6_magic(&ip->v6->saddr, &ip->v6->daddr, 0, proto, 0); -} - -#endif