未验证 提交 04988a23 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!1724 Net: ethernet: Support management channel of the host tool in 3snic 3s9xx network driver

Merge Pull Request from: @steven-song3 
 
3snic inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I7MVPN
CVE:NA

--------------------------------

The driver supports 3snic 3s9xx serial network cards (100GE (40GE
compatible)-3S930 and 25GE (10GE compatible)-3S910/3S920).

Feature:
1. Support firmware update and active
2. Support online log collection
3. Network card information query: Gemini information, version,
Optical module information, tx/rx queue information,
Serdes information, bond information, etc
4. Support Relevant parameter settings: tx speed limit,
port rate, port adaptive mode, setting lro aggregation
time and number, Factory reset, etc
Reviewed-by: NChen Mou <chenmou@3snic.com>
Reviewed-by: NWan Renyong <wanry@3snic.com>
Reviewed-by: NYang Gan <yanggan@3snic.com>
Reviewed-by: NWen Liang <wenliang@3snic.com>
Signed-off-by: NSteven Song <steven.song@3snic.com>

==================================

Test:
compille: pass
insmod/rmmod: pass
iperf: Pass 
 
Link:https://gitee.com/openeuler/kernel/pulls/1724 

Reviewed-by: Jialin Zhang <zhangjialin11@huawei.com> 
Signed-off-by: Jialin Zhang <zhangjialin11@huawei.com> 
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2023 3SNIC
#
SYS_TIME=$(shell date +%Y-%m-%d_%H:%M:%S)
ccflags-y += -D __TIME_STR__=\"$(SYS_TIME)\"
ccflags-y += -I$(srctree)/drivers/net/ethernet/3snic/sssnic/hw
ccflags-y += -I$(srctree)/drivers/net/ethernet/3snic/sssnic/hw/tool
ccflags-y += -I$(srctree)/drivers/net/ethernet/3snic/sssnic/include
ccflags-y += -I$(srctree)/drivers/net/ethernet/3snic/sssnic/include/hw
ccflags-y += -I$(srctree)/drivers/net/ethernet/3snic/sssnic/include/kernel
......@@ -45,4 +48,8 @@ sssdk-y := sss_hw_main.o \
sss_common.o \
sss_wq.o \
sss_hwif_ceq.o \
sss_adapter_mgmt.o
sss_adapter_mgmt.o \
./tool/sss_tool_main.o \
./tool/sss_tool_chip.o \
./tool/sss_tool_sdk.o \
./tool/sss_tool_sm.o
......@@ -15,7 +15,7 @@
#include "sss_hw_svc_cap.h"
#include "sss_sriov_info.h"
#define SSS_MAX_FUNCTION_NUM 4096
#define SSS_MAX_FUNC 4096
struct sss_card_node {
struct list_head node;
......@@ -23,7 +23,10 @@ struct sss_card_node {
char chip_name[IFNAMSIZ];
u8 bus_id;
u8 resvd[7];
u16 func_num;
atomic_t channel_timeout_cnt;
void *func_handle_array[SSS_MAX_FUNC];
void *dbgtool_info;
};
/* Structure pcidev private */
......@@ -57,6 +60,11 @@ struct sss_pci_adapter {
struct sss_sriov_info sriov_info;
atomic_t ref_cnt;
atomic_t uld_ref_cnt[SSS_SERVICE_TYPE_MAX];
spinlock_t uld_lock; /* protect uld probe and remove */
/* set when uld driver processing event */
unsigned long uld_run_state;
......@@ -65,7 +73,6 @@ struct sss_pci_adapter {
/* lock for attach/detach uld */
struct mutex uld_attach_mutex;
/* spin lock for uld_attach_state access */
spinlock_t dettach_uld_lock;
spinlock_t dettach_uld_lock; /* spin lock for uld_attach_state access */
};
#endif
......@@ -93,7 +93,7 @@ struct sss_adm_msg {
u32 ci;
struct semaphore sem;
spinlock_t async_lock; /* protect adm msg async and sync */
dma_addr_t wb_state_paddr;
dma_addr_t head_elem_paddr;
......
......@@ -4,11 +4,11 @@
#ifndef SSS_CSR_H
#define SSS_CSR_H
#define SSS_CSR_CFG_FLAG 0x40000000
#define SSS_CSR_CFG_FLAG 0x40000000
#define SSS_MGMT_FLAG 0xC0000000
#define SSS_CSR_FLAG_MASK 0x3FFFFFFF
#define SSS_CSR_FLAG_MASK 0x3FFFFFFF
#define SSS_VF_CFG_REG_OFFSET 0x2000
......@@ -25,7 +25,7 @@
#define SSS_CSR_HW_ATTR6_ADDR (SSS_CSR_CFG_FLAG + 0x18)
#define SSS_HW_CSR_MBX_DATA_OFF 0x80
#define SSS_HW_CSR_MBX_CTRL_OFF (SSS_CSR_CFG_FLAG + 0x0100)
#define SSS_HW_CSR_MBX_CTRL_OFF (SSS_CSR_CFG_FLAG + 0x0100)
#define SSS_HW_CSR_MBX_INT_OFFSET_OFF (SSS_CSR_CFG_FLAG + 0x0104)
#define SSS_HW_CSR_MBX_RES_H_OFF (SSS_CSR_CFG_FLAG + 0x0108)
#define SSS_HW_CSR_MBX_RES_L_OFF (SSS_CSR_CFG_FLAG + 0x010C)
......@@ -46,27 +46,41 @@
(SSS_CSR_HW_PPF_ELECT_BASE_ADDR + \
(host_id) * SSS_CSR_HW_PPF_ELECT_PORT_STRIDE)
#define SSS_CSR_DMA_ATTR_TBL_ADDR (SSS_CSR_CFG_FLAG + 0x380)
#define SSS_CSR_DMA_ATTR_TBL_ADDR (SSS_CSR_CFG_FLAG + 0x380)
#define SSS_CSR_DMA_ATTR_INDIR_ID_ADDR (SSS_CSR_CFG_FLAG + 0x390)
/* CLP registers */
#define SSS_BAR3_CLP_BASE_ADDR (SSS_MGMT_FLAG + 0x0000)
#define SSS_UCPU_CLP_SIZE_REG (SSS_HOST_CSR_BASE_ADDR + 0x40)
#define SSS_UCPU_CLP_REQBASE_REG (SSS_HOST_CSR_BASE_ADDR + 0x44)
#define SSS_UCPU_CLP_RSPBASE_REG (SSS_HOST_CSR_BASE_ADDR + 0x48)
#define SSS_UCPU_CLP_REQ_REG (SSS_HOST_CSR_BASE_ADDR + 0x4c)
#define SSS_UCPU_CLP_RSP_REG (SSS_HOST_CSR_BASE_ADDR + 0x50)
#define SSS_CLP_REG(member) (SSS_UCPU_CLP_##member##_REG)
#define SSS_CLP_REQ_DATA SSS_BAR3_CLP_BASE_ADDR
#define SSS_CLP_RSP_DATA (SSS_BAR3_CLP_BASE_ADDR + 0x1000)
#define SSS_CLP_DATA(member) (SSS_CLP_##member##_DATA)
/* MSI-X registers */
#define SSS_CSR_MSIX_INDIR_ID_ADDR (SSS_CSR_CFG_FLAG + 0x310)
#define SSS_CSR_MSIX_CTRL_ADDR (SSS_CSR_CFG_FLAG + 0x300)
#define SSS_CSR_MSIX_CNT_ADDR (SSS_CSR_CFG_FLAG + 0x304)
#define SSS_CSR_FUNC_MSI_CLR_WR_ADDR (SSS_CSR_CFG_FLAG + 0x58)
#define SSS_CSR_FUNC_MSI_CLR_WR_ADDR (SSS_CSR_CFG_FLAG + 0x58)
#define SSS_MSI_CLR_INDIR_RESEND_TIMER_CLR_SHIFT 0
#define SSS_MSI_CLR_INDIR_INT_MSK_SET_SHIFT 1
#define SSS_MSI_CLR_INDIR_INT_MSK_CLR_SHIFT 2
#define SSS_MSI_CLR_INDIR_INT_MSK_SET_SHIFT 1
#define SSS_MSI_CLR_INDIR_INT_MSK_CLR_SHIFT 2
#define SSS_MSI_CLR_INDIR_AUTO_MSK_SET_SHIFT 3
#define SSS_MSI_CLR_INDIR_AUTO_MSK_CLR_SHIFT 4
#define SSS_MSI_CLR_INDIR_SIMPLE_INDIR_ID_SHIFT 22
#define SSS_MSI_CLR_INDIR_RESEND_TIMER_CLR_MASK 0x1U
#define SSS_MSI_CLR_INDIR_INT_MSK_SET_MASK 0x1U
#define SSS_MSI_CLR_INDIR_INT_MSK_CLR_MASK 0x1U
#define SSS_MSI_CLR_INDIR_AUTO_MSK_SET_MASK 0x1U
#define SSS_MSI_CLR_INDIR_AUTO_MSK_CLR_MASK 0x1U
#define SSS_MSI_CLR_INDIR_INT_MSK_SET_MASK 0x1U
#define SSS_MSI_CLR_INDIR_INT_MSK_CLR_MASK 0x1U
#define SSS_MSI_CLR_INDIR_AUTO_MSK_SET_MASK 0x1U
#define SSS_MSI_CLR_INDIR_AUTO_MSK_CLR_MASK 0x1U
#define SSS_MSI_CLR_INDIR_SIMPLE_INDIR_ID_MASK 0x3FFU
#define SSS_SET_MSI_CLR_INDIR(val, member) \
......@@ -80,8 +94,8 @@
#define SSS_EQ_INDIR_ID_ADDR(type) \
((type == SSS_AEQ) ? SSS_AEQ_INDIR_ID_ADDR : SSS_CEQ_INDIR_ID_ADDR)
#define SSS_AEQ_MTT_OFF_BASE_ADDR (SSS_CSR_CFG_FLAG + 0x240)
#define SSS_CEQ_MTT_OFF_BASE_ADDR (SSS_CSR_CFG_FLAG + 0x2C0)
#define SSS_AEQ_MTT_OFF_BASE_ADDR (SSS_CSR_CFG_FLAG + 0x240)
#define SSS_CEQ_MTT_OFF_BASE_ADDR (SSS_CSR_CFG_FLAG + 0x2C0)
#define SSS_CSR_EQ_PAGE_OFF_STRIDE 8
......@@ -98,20 +112,20 @@
(SSS_CEQ_MTT_OFF_BASE_ADDR + \
(pg_num) * SSS_CSR_EQ_PAGE_OFF_STRIDE + 4)
#define SSS_CSR_AEQ_CTRL_0_ADDR (SSS_CSR_CFG_FLAG + 0x200)
#define SSS_CSR_AEQ_CTRL_1_ADDR (SSS_CSR_CFG_FLAG + 0x204)
#define SSS_CSR_AEQ_CI_ADDR (SSS_CSR_CFG_FLAG + 0x208)
#define SSS_CSR_AEQ_PI_ADDR (SSS_CSR_CFG_FLAG + 0x20C)
#define SSS_CSR_AEQ_CTRL_0_ADDR (SSS_CSR_CFG_FLAG + 0x200)
#define SSS_CSR_AEQ_CTRL_1_ADDR (SSS_CSR_CFG_FLAG + 0x204)
#define SSS_CSR_AEQ_CI_ADDR (SSS_CSR_CFG_FLAG + 0x208)
#define SSS_CSR_AEQ_PI_ADDR (SSS_CSR_CFG_FLAG + 0x20C)
#define SSS_CSR_AEQ_CI_SIMPLE_INDIR_ADDR (SSS_CSR_CFG_FLAG + 0x50)
#define SSS_CSR_CEQ_CTRL_0_ADDR (SSS_CSR_CFG_FLAG + 0x280)
#define SSS_CSR_CEQ_CTRL_1_ADDR (SSS_CSR_CFG_FLAG + 0x284)
#define SSS_CSR_CEQ_CI_ADDR (SSS_CSR_CFG_FLAG + 0x288)
#define SSS_CSR_CEQ_PI_ADDR (SSS_CSR_CFG_FLAG + 0x28c)
#define SSS_CSR_CEQ_CTRL_0_ADDR (SSS_CSR_CFG_FLAG + 0x280)
#define SSS_CSR_CEQ_CTRL_1_ADDR (SSS_CSR_CFG_FLAG + 0x284)
#define SSS_CSR_CEQ_CI_ADDR (SSS_CSR_CFG_FLAG + 0x288)
#define SSS_CSR_CEQ_PI_ADDR (SSS_CSR_CFG_FLAG + 0x28c)
#define SSS_CSR_CEQ_CI_SIMPLE_INDIR_ADDR (SSS_CSR_CFG_FLAG + 0x54)
/* ADM MSG registers */
#define SSS_CSR_ADM_MSG_BASE (SSS_MGMT_FLAG + 0x2000)
#define SSS_CSR_ADM_MSG_BASE (SSS_MGMT_FLAG + 0x2000)
#define SSS_CSR_ADM_MSG_STRIDE 0x80
......@@ -143,12 +157,12 @@
(SSS_CSR_ADM_MSG_BASE + 0x30 + (id) * SSS_CSR_ADM_MSG_STRIDE)
/* self test register */
#define SSS_MGMT_HEALTH_STATUS_ADDR (SSS_MGMT_FLAG + 0x983c)
#define SSS_MGMT_HEALTH_STATUS_ADDR (SSS_MGMT_FLAG + 0x983c)
#define SSS_CHIP_BASE_INFO_ADDR (SSS_MGMT_FLAG + 0xB02C)
#define SSS_CHIP_BASE_INFO_ADDR (SSS_MGMT_FLAG + 0xB02C)
#define SSS_CHIP_ERR_STATUS0_ADDR (SSS_MGMT_FLAG + 0xC0EC)
#define SSS_CHIP_ERR_STATUS1_ADDR (SSS_MGMT_FLAG + 0xC0F0)
#define SSS_CHIP_ERR_STATUS0_ADDR (SSS_MGMT_FLAG + 0xC0EC)
#define SSS_CHIP_ERR_STATUS1_ADDR (SSS_MGMT_FLAG + 0xC0F0)
#define SSS_ERR_INFO0_ADDR (SSS_MGMT_FLAG + 0xC0F4)
#define SSS_ERR_INFO1_ADDR (SSS_MGMT_FLAG + 0xC0F8)
......
......@@ -24,6 +24,8 @@
#include "sss_mbx_info.h"
#include "sss_mgmt_channel.h"
#define SSSNIC_CHANNEL_DETECT_PERIOD (5 * 1000)
enum sss_func_mode {
SSS_FUNC_MOD_MIN,
......@@ -81,6 +83,11 @@ struct sss_aeq_stat {
u64 last_recv_cnt;
};
struct sss_clp_pf_to_mgmt {
struct semaphore clp_msg_lock;
void *clp_msg_buf;
};
struct sss_hwdev {
void *adapter_hdl; /* pointer to sss_pci_adapter or NDIS_Adapter */
void *pcidev_hdl; /* pointer to pcidev or Handler */
......@@ -108,6 +115,7 @@ struct sss_hwdev {
struct sss_ceq_info *ceq_info;
struct sss_mbx *mbx; // mbx
struct sss_msg_pf_to_mgmt *pf_to_mgmt; // adm
struct sss_clp_pf_to_mgmt *clp_pf_to_mgmt;
struct sss_hw_stats hw_stats;
u8 *chip_fault_stats;
......@@ -132,6 +140,8 @@ struct sss_hwdev {
enum sss_func_mode func_mode;
struct sss_aeq_stat aeq_stat;
u16 aeq_busy_cnt;
};
#define SSS_TO_HWDEV(ptr) ((struct sss_hwdev *)(ptr)->hwdev)
......@@ -220,6 +230,8 @@ enum sss_servic_bit_define {
#define SSS_IS_PPF(dev) \
(SSS_GET_FUNC_TYPE(dev) == SSS_FUNC_TYPE_PPF)
#define SSS_GET_FUNC_ID(hwdev) ((hwdev)->hwif->attr.func_id)
#define SSS_IS_BMGW_MASTER_HOST(hwdev) \
((hwdev)->func_mode == SSS_FUNC_MOD_MULTI_BM_MASTER)
#define SSS_IS_BMGW_SLAVE_HOST(hwdev) \
......@@ -248,6 +260,10 @@ enum sss_servic_bit_define {
((hwdev)->features[0] & SSS_COMM_F_CTRLQ_NUM)
#define SSS_SUPPORT_VIRTIO_VQ_SIZE(hwdev) \
((hwdev)->features[0] & SSS_COMM_F_VIRTIO_VQ_SIZE)
#define SSS_SUPPORT_CHANNEL_DETECT(hwdev) \
((hwdev)->features[0] & SSS_COMM_F_CHANNEL_DETECT)
#define SSS_SUPPORT_CLP(hwdev) \
((hwdev)->features[0] & SSS_COMM_F_CLP)
enum {
SSS_CFG_FREE = 0,
......
......@@ -109,29 +109,33 @@ struct sss_recv_msg {
};
struct sss_msg_pf_to_mgmt {
void *hwdev;
void *hwdev;
spinlock_t async_msg_lock; /* protect msg async and sync */
struct semaphore sync_lock;
struct semaphore sync_lock;
struct workqueue_struct *workq;
struct workqueue_struct *workq;
void *async_msg_buf;
void *sync_buf;
void *ack_buf;
struct sss_recv_msg recv_msg;
struct sss_recv_msg recv_resp_msg;
struct sss_recv_msg recv_msg;
struct sss_recv_msg recv_resp_msg;
u16 rsvd;
u16 sync_msg_id;
struct sss_adm_msg adm_msg;
u16 rsvd;
u16 async_msg_id;
u16 sync_msg_id;
struct sss_adm_msg *adm_msg[SSS_ADM_MSG_MAX];
sss_mgmt_msg_handler_t recv_handler[SSS_MOD_TYPE_HW_MAX];
void *recv_data[SSS_MOD_TYPE_HW_MAX];
unsigned long recv_handler_state[SSS_MOD_TYPE_HW_MAX];
sss_mgmt_msg_handler_t recv_handler[SSS_MOD_TYPE_HW_MAX];
void *recv_data[SSS_MOD_TYPE_HW_MAX];
unsigned long recv_handler_state[SSS_MOD_TYPE_HW_MAX];
void *async_msg_cb_data[SSS_MOD_TYPE_HW_MAX];
/* lock when sending msg */
spinlock_t sync_event_lock;
enum sss_pf_to_mgmt_event_state event_state;
spinlock_t sync_event_lock; /* protect event async and sync */
enum sss_pf_to_mgmt_event_state event_state;
};
#endif
......@@ -107,6 +107,11 @@ struct sss_service_cap {
struct sss_vbs_service_cap vbs_cap; /* VBS capability */
};
struct sss_svc_cap_info {
u32 func_id;
struct sss_service_cap cap;
};
struct sss_mgmt_info {
void *hwdev;
struct sss_service_cap svc_cap;
......
......@@ -17,21 +17,31 @@
#include "sss_kernel.h"
#include "sss_hw.h"
#include "sss_hwdev.h"
#include "sss_pci_sriov.h"
#include "sss_pci_id_tbl.h"
#include "sss_adapter.h"
#include "sss_adapter_mgmt.h"
#include "sss_pci_global.h"
#include "sss_tool_comm.h"
#include "sss_hw_export.h"
#include "sss_tool_hw.h"
#include "sss_tool.h"
#ifndef SSS_PF_NUM_MAX
#define SSS_PF_NUM_MAX (16)
#endif
#define SSS_ADAPTER_CNT_TIMEOUT 10000
#define SSS_WAIT_ADAPTER_USLEEP_MIN 9900
#define SSS_WAIT_ADAPTER_USLEEP_MAX 10000
#define SSS_CHIP_NODE_HOLD_TIMEOUT (10 * 60 * 1000)
#define SSS_WAIT_CHIP_NODE_CHANGED (10 * 60 * 1000)
#define SSS_PRINT_TIMEOUT_INTERVAL 10000
#define SSS_MICRO_SECOND 1000
#define SSS_CHIP_NODE_USLEEP_MIN 900
#define SSS_CHIP_NODE_USLEEP_MAX 1000
#define SSS_CHIP_NODE_HOLD_TIMEOUT (10 * 60 * 1000)
#define SSS_WAIT_CHIP_NODE_CHANGED (10 * 60 * 1000)
#define SSS_PRINT_TIMEOUT_INTERVAL 10000
#define SSS_MICRO_SECOND 1000
#define SSS_CHIP_NODE_USLEEP_MIN 900
#define SSS_CHIP_NODE_USLEEP_MAX 1000
#define SSS_CARD_CNT_MAX 64
......@@ -42,10 +52,9 @@ enum sss_node_state {
};
struct sss_chip_node_lock {
/* lock for chip list */
struct mutex chip_mutex;
unsigned long state;
atomic_t ref_cnt;
struct mutex chip_mutex; /* lock for chip list */
unsigned long state;
atomic_t ref_cnt;
};
static struct sss_chip_node_lock g_chip_node_lock;
......@@ -59,7 +68,21 @@ struct list_head *sss_get_chip_list(void)
return &g_chip_list;
}
static void sss_chip_node_lock(void)
void lld_dev_hold(struct sss_hal_dev *dev)
{
struct sss_pci_adapter *pci_adapter = pci_get_drvdata(dev->pdev);
atomic_inc(&pci_adapter->ref_cnt);
}
void lld_dev_put(struct sss_hal_dev *dev)
{
struct sss_pci_adapter *pci_adapter = pci_get_drvdata(dev->pdev);
atomic_dec(&pci_adapter->ref_cnt);
}
void sss_chip_node_lock(void)
{
unsigned long end;
bool timeout = true;
......@@ -81,8 +104,7 @@ static void sss_chip_node_lock(void)
loop_cnt / SSS_MICRO_SECOND);
/* if sleep 1ms, use usleep_range to be more precise */
usleep_range(SSS_CHIP_NODE_USLEEP_MIN,
SSS_CHIP_NODE_USLEEP_MAX);
usleep_range(SSS_CHIP_NODE_USLEEP_MIN, SSS_CHIP_NODE_USLEEP_MAX);
} while (time_before(jiffies, end));
if (timeout && test_and_set_bit(SSS_NODE_CHANGE, &g_chip_node_lock.state))
......@@ -113,7 +135,7 @@ static void sss_chip_node_lock(void)
mutex_unlock(&g_chip_node_lock.chip_mutex);
}
static void sss_chip_node_unlock(void)
void sss_chip_node_unlock(void)
{
clear_bit(SSS_NODE_CHANGE, &g_chip_node_lock.state);
}
......@@ -136,8 +158,7 @@ void sss_hold_chip_node(void)
pr_warn("Wait adapter change complete for %us\n",
loop_cnt / SSS_MICRO_SECOND);
/* if sleep 1ms, use usleep_range to be more precise */
usleep_range(SSS_CHIP_NODE_USLEEP_MIN,
SSS_CHIP_NODE_USLEEP_MAX);
usleep_range(SSS_CHIP_NODE_USLEEP_MIN, SSS_CHIP_NODE_USLEEP_MAX);
} while (time_before(jiffies, end));
if (test_bit(SSS_NODE_CHANGE, &g_chip_node_lock.state))
......@@ -295,8 +316,7 @@ void sss_free_chip_node(struct sss_pci_adapter *adapter)
if (ret < 0)
sdk_err(&adapter->pcidev->dev, "Fail to get nic id\n");
clear_bit(id, &g_index_bit_map);
sss_free_card_id(id);
kfree(chip_node);
}
sss_chip_node_unlock();
......@@ -315,3 +335,390 @@ void sss_del_func_list(struct sss_pci_adapter *adapter)
list_del(&adapter->node);
sss_chip_node_unlock();
}
static struct sss_card_node *sss_get_chip_node_by_hwdev(const void *hwdev)
{
struct sss_card_node *chip_node = NULL;
struct sss_card_node *node_tmp = NULL;
struct sss_pci_adapter *dev = NULL;
if (!hwdev)
return NULL;
sss_hold_chip_node();
list_for_each_entry(node_tmp, &g_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;
}
}
}
}
sss_put_chip_node();
return chip_node;
}
static bool sss_is_func_valid(struct sss_pci_adapter *dev)
{
if (sss_get_func_type(dev->hwdev) == SSS_FUNC_TYPE_VF)
return false;
return true;
}
static int sss_get_dynamic_uld_dev_name(struct sss_pci_adapter *dev, enum sss_service_type type,
char *ifname)
{
u32 out_size = IFNAMSIZ;
struct sss_uld_info *uld_info = sss_get_uld_info();
if (!uld_info[type].ioctl)
return -EFAULT;
return uld_info[type].ioctl(dev->uld_dev[type], SSS_TOOL_GET_ULD_DEV_NAME,
NULL, 0, ifname, &out_size);
}
static bool sss_support_service_type(void *hwdev)
{
struct sss_hwdev *dev = hwdev;
if (!hwdev)
return false;
return !dev->mgmt_info->svc_cap.chip_svc_type;
}
void sss_get_card_info(const void *hwdev, void *bufin)
{
struct sss_card_node *chip_node = NULL;
struct sss_tool_card_info *info = (struct sss_tool_card_info *)bufin;
struct sss_pci_adapter *dev = NULL;
void *fun_hwdev = NULL;
u32 i = 0;
info->pf_num = 0;
chip_node = sss_get_chip_node_by_hwdev(hwdev);
if (!chip_node)
return;
sss_hold_chip_node();
list_for_each_entry(dev, &chip_node->func_list, node) {
if (!sss_is_func_valid(dev))
continue;
fun_hwdev = dev->hwdev;
if (sss_support_nic(fun_hwdev)) {
if (dev->uld_dev[SSS_SERVICE_TYPE_NIC]) {
info->pf[i].pf_type |= (u32)BIT(SSS_SERVICE_TYPE_NIC);
sss_get_dynamic_uld_dev_name(dev, SSS_SERVICE_TYPE_NIC,
info->pf[i].name);
}
}
if (sss_support_ppa(fun_hwdev, NULL)) {
if (dev->uld_dev[SSS_SERVICE_TYPE_PPA]) {
info->pf[i].pf_type |= (u32)BIT(SSS_SERVICE_TYPE_PPA);
sss_get_dynamic_uld_dev_name(dev, SSS_SERVICE_TYPE_PPA,
info->pf[i].name);
}
}
if (sss_support_service_type(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;
}
sss_put_chip_node();
}
bool sss_is_in_host(void)
{
struct sss_card_node *node = NULL;
struct sss_pci_adapter *adapter = NULL;
sss_hold_chip_node();
list_for_each_entry(node, &g_chip_list, node) {
list_for_each_entry(adapter, &node->func_list, node) {
if (sss_get_func_type(adapter->hwdev) != SSS_FUNC_TYPE_VF) {
sss_put_chip_node();
return true;
}
}
}
sss_put_chip_node();
return false;
}
void sss_get_all_chip_id(void *id_info)
{
int i = 0;
int id;
int ret;
struct sss_card_id *card_id = (struct sss_card_id *)id_info;
struct sss_card_node *node = NULL;
sss_hold_chip_node();
list_for_each_entry(node, &g_chip_list, node) {
ret = sscanf(node->chip_name, SSS_CHIP_NAME "%d", &id);
if (ret < 0) {
pr_err("Fail to get chip id\n");
continue;
}
card_id->id[i] = (u32)id;
i++;
}
sss_put_chip_node();
card_id->num = (u32)i;
}
void *sss_get_pcidev_hdl(void *hwdev)
{
struct sss_hwdev *dev = (struct sss_hwdev *)hwdev;
if (!hwdev)
return NULL;
return dev->pcidev_hdl;
}
struct sss_card_node *sss_get_card_node(struct sss_hal_dev *hal_dev)
{
struct sss_pci_adapter *adapter = pci_get_drvdata(hal_dev->pdev);
return adapter->chip_node;
}
void sss_get_card_func_info(const char *chip_name, struct sss_card_func_info *card_func)
{
struct sss_card_node *card_node = NULL;
struct sss_pci_adapter *adapter = NULL;
struct sss_func_pdev_info *info = NULL;
card_func->pf_num = 0;
sss_hold_chip_node();
list_for_each_entry(card_node, &g_chip_list, node) {
if (strncmp(card_node->chip_name, chip_name, IFNAMSIZ))
continue;
list_for_each_entry(adapter, &card_node->func_list, node) {
if (sss_get_func_type(adapter->hwdev) == SSS_FUNC_TYPE_VF)
continue;
info = &card_func->pdev_info[card_func->pf_num];
info->bar1_size =
pci_resource_len(adapter->pcidev, SSS_PF_PCI_CFG_REG_BAR);
info->bar1_pa =
pci_resource_start(adapter->pcidev, SSS_PF_PCI_CFG_REG_BAR);
info->bar3_size =
pci_resource_len(adapter->pcidev, SSS_PCI_MGMT_REG_BAR);
info->bar3_pa =
pci_resource_start(adapter->pcidev, SSS_PCI_MGMT_REG_BAR);
card_func->pf_num++;
if (card_func->pf_num >= SSS_PF_NUM_MAX) {
sss_put_chip_node();
return;
}
}
}
sss_put_chip_node();
}
int sss_get_pf_id(struct sss_card_node *card_node, u32 port_id, u32 *pf_id, u32 *valid)
{
struct sss_pci_adapter *adapter = NULL;
sss_hold_chip_node();
list_for_each_entry(adapter, &card_node->func_list, node) {
if (sss_get_func_type(adapter->hwdev) == SSS_FUNC_TYPE_VF)
continue;
if (SSS_TO_PHY_PORT_ID(adapter->hwdev) == port_id) {
*pf_id = sss_get_func_id(adapter->hwdev);
*valid = 1;
break;
}
}
sss_put_chip_node();
return 0;
}
void *sss_get_uld_dev(struct sss_hal_dev *hal_dev, enum sss_service_type type)
{
struct sss_pci_adapter *dev = NULL;
void *uld = NULL;
if (!hal_dev)
return NULL;
dev = pci_get_drvdata(hal_dev->pdev);
if (!dev)
return NULL;
spin_lock_bh(&dev->uld_lock);
if (!dev->uld_dev[type] || !test_bit(type, &dev->uld_attach_state)) {
spin_unlock_bh(&dev->uld_lock);
return NULL;
}
uld = dev->uld_dev[type];
atomic_inc(&dev->uld_ref_cnt[type]);
spin_unlock_bh(&dev->uld_lock);
return uld;
}
void sss_uld_dev_put(struct sss_hal_dev *hal_dev, enum sss_service_type type)
{
struct sss_pci_adapter *pci_adapter = pci_get_drvdata(hal_dev->pdev);
atomic_dec(&pci_adapter->uld_ref_cnt[type]);
}
static bool sss_is_pcidev_match_dev_name(const char *dev_name, struct sss_pci_adapter *dev,
enum sss_service_type type)
{
enum sss_service_type i;
char nic_uld_name[IFNAMSIZ] = {0};
int err;
if (type > SSS_SERVICE_TYPE_MAX)
return false;
if (type == SSS_SERVICE_TYPE_MAX) {
for (i = SSS_SERVICE_TYPE_OVS; i < SSS_SERVICE_TYPE_MAX; i++) {
if (!strncmp(dev->uld_dev_name[i], dev_name, IFNAMSIZ))
return true;
}
} else {
if (!strncmp(dev->uld_dev_name[type], dev_name, IFNAMSIZ))
return true;
}
err = sss_get_dynamic_uld_dev_name(dev, SSS_SERVICE_TYPE_NIC, (char *)nic_uld_name);
if (err == 0) {
if (!strncmp(nic_uld_name, dev_name, IFNAMSIZ))
return true;
}
return false;
}
struct sss_hal_dev *sss_get_lld_dev_by_dev_name(const char *dev_name, enum sss_service_type type)
{
struct sss_card_node *chip_node = NULL;
struct sss_pci_adapter *dev = NULL;
sss_hold_chip_node();
list_for_each_entry(chip_node, &g_chip_list, node) {
list_for_each_entry(dev, &chip_node->func_list, node) {
if (sss_is_pcidev_match_dev_name(dev_name, dev, type)) {
lld_dev_hold(&dev->hal_dev);
sss_put_chip_node();
return &dev->hal_dev;
}
}
}
sss_put_chip_node();
return NULL;
}
static bool sss_is_pcidev_match_chip_name(const char *ifname, struct sss_pci_adapter *dev,
struct sss_card_node *chip_node, enum sss_func_type type)
{
if (!strncmp(chip_node->chip_name, ifname, IFNAMSIZ)) {
if (sss_get_func_type(dev->hwdev) != type)
return false;
return true;
}
return false;
}
static struct sss_hal_dev *sss_get_dst_type_lld_dev_by_chip_name(const char *ifname,
enum sss_func_type type)
{
struct sss_card_node *chip_node = NULL;
struct sss_pci_adapter *dev = NULL;
list_for_each_entry(chip_node, &g_chip_list, node) {
list_for_each_entry(dev, &chip_node->func_list, node) {
if (sss_is_pcidev_match_chip_name(ifname, dev, chip_node, type))
return &dev->hal_dev;
}
}
return NULL;
}
struct sss_hal_dev *sss_get_lld_dev_by_chip_name(const char *chip_name)
{
struct sss_hal_dev *dev = NULL;
sss_hold_chip_node();
dev = sss_get_dst_type_lld_dev_by_chip_name(chip_name, SSS_FUNC_TYPE_PPF);
if (dev)
goto out;
dev = sss_get_dst_type_lld_dev_by_chip_name(chip_name, SSS_FUNC_TYPE_PF);
if (dev)
goto out;
dev = sss_get_dst_type_lld_dev_by_chip_name(chip_name, SSS_FUNC_TYPE_VF);
out:
if (dev)
lld_dev_hold(dev);
sss_put_chip_node();
return dev;
}
struct sss_hal_dev *sss_get_lld_dev_by_chip_and_port(const char *chip_name, u8 port_id)
{
struct sss_card_node *chip_node = NULL;
struct sss_pci_adapter *dev = NULL;
sss_hold_chip_node();
list_for_each_entry(chip_node, &g_chip_list, node) {
list_for_each_entry(dev, &chip_node->func_list, node) {
if (sss_get_func_type(dev->hwdev) == SSS_FUNC_TYPE_VF)
continue;
if (SSS_TO_PHY_PORT_ID(dev->hwdev) == port_id &&
!strncmp(chip_node->chip_name, chip_name, IFNAMSIZ)) {
lld_dev_hold(&dev->hal_dev);
sss_put_chip_node();
return &dev->hal_dev;
}
}
}
sss_put_chip_node();
return NULL;
}
......@@ -7,8 +7,11 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include "sss_version.h"
#include "sss_adapter.h"
#define SSS_DRV_VERSION SSS_VERSION_STR
#define SSS_DRV_NAME "sssdk"
#define SSS_CHIP_NAME "sssnic"
......@@ -21,6 +24,30 @@
#define SSS_IS_VF_DEV(pdev) ((pdev)->device == SSS_DEV_ID_VF)
#define SSS_CARD_MAX_SIZE (64)
struct sss_card_id {
u32 id[SSS_CARD_MAX_SIZE];
u32 num;
};
struct sss_func_pdev_info {
u64 bar0_pa;
u64 bar0_size;
u64 bar1_pa;
u64 bar1_size;
u64 bar3_pa;
u64 bar3_size;
u64 rsvd[4];
};
struct sss_card_func_info {
u32 pf_num;
u32 rsvd;
u64 usr_adm_pa;
struct sss_func_pdev_info pdev_info[SSS_CARD_MAX_SIZE];
};
enum {
SSS_NO_PROBE = 1,
SSS_PROBE_START = 2,
......@@ -40,4 +67,34 @@ void sss_put_chip_node(void);
void sss_set_adapter_probe_state(struct sss_pci_adapter *adapter, int state);
void lld_dev_hold(struct sss_hal_dev *dev);
void lld_dev_put(struct sss_hal_dev *dev);
void sss_chip_node_lock(void);
void sss_chip_node_unlock(void);
void *sss_get_pcidev_hdl(void *hwdev);
void *sss_get_uld_dev(struct sss_hal_dev *hal_dev, enum sss_service_type type);
void sss_uld_dev_put(struct sss_hal_dev *hal_dev, enum sss_service_type type);
struct sss_hal_dev *sss_get_lld_dev_by_dev_name(const char *dev_name, enum sss_service_type type);
struct sss_hal_dev *sss_get_lld_dev_by_chip_name(const char *chip_name);
struct sss_hal_dev *sss_get_lld_dev_by_chip_and_port(const char *chip_name, u8 port_id);
void sss_get_all_chip_id(void *id_info);
void sss_get_card_func_info
(const char *chip_name, struct sss_card_func_info *card_func);
void sss_get_card_info(const void *hwdev, void *bufin);
bool sss_is_in_host(void);
int sss_get_pf_id(struct sss_card_node *chip_node, u32 port_id, u32 *pf_id, u32 *valid);
struct sss_card_node *sss_get_card_node(struct sss_hal_dev *hal_dev);
#endif
......@@ -27,7 +27,6 @@
#include "sss_pci_shutdown.h"
#include "sss_pci_error.h"
#define SSS_DRV_VERSION SSS_VERSION_STR
#define SSS_DRV_DESC "Intelligent Network Interface Card Driver"
MODULE_AUTHOR("steven.song@3snic.com");
......
......@@ -280,7 +280,7 @@ static void sss_print_pubic_cap(void *dev_hdl, const struct sss_service_cap *svc
svc_cap->pseudo_vf_bfilter_start_addr, svc_cap->pseudo_vf_bfilter_len);
}
static void sss_parse_cqm_cap(struct sss_hwdev *hwdev,
static void sss_parse_qmm_cap(struct sss_hwdev *hwdev,
struct sss_service_cap *svc_cap, struct sss_cmd_dev_cap_cfg *cmd_cap)
{
struct sss_dev_sf_svc_attr *sf_svc_attr = &svc_cap->sf_svc_attr;
......@@ -346,7 +346,7 @@ static void sss_parse_pubic_cap(struct sss_hwdev *hwdev,
svc_cap->sf_en = (type == SSS_FUNC_TYPE_PPF) ?
(!!cmd_cap->host_sf_en) : (!!cmd_cap->func_sf_en);
sss_parse_cqm_cap(hwdev, svc_cap, cmd_cap);
sss_parse_qmm_cap(hwdev, svc_cap, cmd_cap);
sss_print_pubic_cap(hwdev->dev_hdl, svc_cap);
}
......
......@@ -12,6 +12,7 @@
#include "sss_hwdev.h"
#include "sss_csr.h"
#include "sss_hwif_api.h"
#include "sss_hw_svc_cap.h"
#define SSS_DEFAULT_RX_BUF_SIZE_LEVEL ((u16)0xB)
......@@ -287,6 +288,23 @@ bool sss_support_nic(void *hwdev)
}
EXPORT_SYMBOL(sss_support_nic);
bool sss_support_ppa(void *hwdev, struct sss_ppa_service_cap *cap)
{
struct sss_hwdev *dev = hwdev;
if (!hwdev)
return false;
if (!SSS_IS_PPA_TYPE(dev))
return false;
if (cap)
memcpy(cap, &dev->mgmt_info->svc_cap.ppa_cap, sizeof(*cap));
return true;
}
EXPORT_SYMBOL(sss_support_ppa);
u16 sss_get_max_sq_num(void *hwdev)
{
if (!hwdev) {
......@@ -320,6 +338,19 @@ u16 sss_get_max_vf_num(void *hwdev)
}
EXPORT_SYMBOL(sss_get_max_vf_num);
u16 sss_nic_intr_num(void *hwdev)
{
struct sss_hwif *hwif = NULL;
if (!hwdev)
return 0;
hwif = ((struct sss_hwdev *)hwdev)->hwif;
return hwif->attr.irq_num;
}
EXPORT_SYMBOL(sss_nic_intr_num);
int sss_get_cos_valid_bitmap(void *hwdev, u8 *func_cos_bitmap, u8 *port_cos_bitmap)
{
if (!hwdev) {
......@@ -561,8 +592,8 @@ void sss_update_link_stats(void *hwdev, bool link_state)
return;
if (link_state)
atomic_inc(&dev->hw_stats.sss_link_event_stats.link_up_stats);
atomic_inc(&dev->hw_stats.link_event_stats.link_up_stats);
else
atomic_inc(&dev->hw_stats.sss_link_event_stats.link_down_stats);
atomic_inc(&dev->hw_stats.link_event_stats.link_down_stats);
}
EXPORT_SYMBOL(sss_update_link_stats);
......@@ -12,6 +12,7 @@
#include "sss_hw_common.h"
#include "sss_hwdev_api.h"
#include "sss_hwif_adm.h"
#include "sss_hwif_adm_common.h"
#define SSS_FW_MAGIC_NUM 0x5a5a1100
#define SSS_FW_IMAGE_HEAD_SIZE 4096
......
......@@ -318,10 +318,10 @@ static void sss_print_chip_fault(struct sss_hwdev *hwdev,
level_str = SSS_FAULT_LEVEL_STR_UNKNOWN;
if (err_level == SSS_FAULT_LEVEL_SERIOUS_FLR)
dev_err(hwdev->dev_hdl, "Err_level: %u [%s], func_id: %u\n",
sdk_err(hwdev->dev_hdl, "Err_level: %u [%s], func_id: %u\n",
err_level, level_str, fault_event->info.chip.func_id);
dev_err(hwdev->dev_hdl, "Node_id: 0x%x, err_type: 0x%x, err_level: %u[%s], err_csr_addr: 0x%08x, err_csr_value: 0x%08x\n",
sdk_err(hwdev->dev_hdl, "Node_id: 0x%x, err_type: 0x%x, err_level: %u[%s], err_csr_addr: 0x%08x, err_csr_value: 0x%08x\n",
fault_event->info.chip.node_id, fault_event->info.chip.err_type,
err_level, level_str,
fault_event->info.chip.err_csr_addr, fault_event->info.chip.err_csr_value);
......@@ -362,7 +362,7 @@ static void sss_print_phy_err(struct sss_hwdev *hwdev,
static void sss_print_fault_info(struct sss_hwdev *hwdev,
struct sss_fault_event *fault_event)
{
struct sss_fault_event_stats *event_stats = &hwdev->hw_stats.sss_fault_event_stats;
struct sss_fault_event_stats *event_stats = &hwdev->hw_stats.fault_event_stats;
char *type = NULL;
char *fault_type[SSS_FAULT_TYPE_MAX] = {
SSS_FAULT_TYPE_STR_CHIP, SSS_FAULT_TYPE_STR_NPU,
......
......@@ -25,63 +25,12 @@
#define SSS_ADM_MSG_ELEM_DESC_SIZE 8
#define SSS_ADM_MSG_ELEM_DATA_ADDR_SIZE 8
#define SSS_ADM_MSG_ELEM_WB_ADDR_SIZE 8
#define SSS_ADM_MSG_ELEM_ALIGNMENT 8
#define SSS_ADM_MSG_STATE_TIMEOUT 10000
#define SSS_WRITE_ADM_MSG_PRIV_DATA(id) (((u8)(id)) << 16)
#define SSS_MASK_ID(adm_msg, id) \
((id) & ((adm_msg)->elem_num - 1))
#define SSS_SIZE_TO_4B(size) \
(ALIGN((u32)(size), 4U) >> 2)
#define SSS_SIZE_TO_8B(size) \
(ALIGN((u32)(size), 8U) >> 3)
/* adm_msg_elem structure */
#define SSS_ADM_MSG_ELEM_CTRL_ELEM_LEN_SHIFT 0
#define SSS_ADM_MSG_ELEM_CTRL_RD_DMA_ATTR_OFF_SHIFT 16
#define SSS_ADM_MSG_ELEM_CTRL_WR_DMA_ATTR_OFF_SHIFT 24
#define SSS_ADM_MSG_ELEM_CTRL_XOR_CHKSUM_SHIFT 56
#define SSS_ADM_MSG_ELEM_CTRL_ELEM_LEN_MASK 0x3FU
#define SSS_ADM_MSG_ELEM_CTRL_RD_DMA_ATTR_OFF_MASK 0x3FU
#define SSS_ADM_MSG_ELEM_CTRL_WR_DMA_ATTR_OFF_MASK 0x3FU
#define SSS_ADM_MSG_ELEM_CTRL_XOR_CHKSUM_MASK 0xFFU
#define SSS_ADM_MSG_ELEM_CTRL_SET(val, member) \
((((u64)(val)) & SSS_ADM_MSG_ELEM_CTRL_##member##_MASK) << \
SSS_ADM_MSG_ELEM_CTRL_##member##_SHIFT)
/* adm_msg_elem.desc structure */
#define SSS_ADM_MSG_DESC_SGL_TYPE_SHIFT 0
#define SSS_ADM_MSG_DESC_RD_WR_SHIFT 1
#define SSS_ADM_MSG_DESC_MGMT_BYPASS_SHIFT 2
#define SSS_ADM_MSG_DESC_REPLY_AEQE_EN_SHIFT 3
#define SSS_ADM_MSG_DESC_MSG_VALID_SHIFT 4
#define SSS_ADM_MSG_DESC_MSG_CHANNEL_SHIFT 6
#define SSS_ADM_MSG_DESC_PRIV_DATA_SHIFT 8
#define SSS_ADM_MSG_DESC_DEST_SHIFT 32
#define SSS_ADM_MSG_DESC_SIZE_SHIFT 40
#define SSS_ADM_MSG_DESC_XOR_CHKSUM_SHIFT 56
#define SSS_ADM_MSG_DESC_SGL_TYPE_MASK 0x1U
#define SSS_ADM_MSG_DESC_RD_WR_MASK 0x1U
#define SSS_ADM_MSG_DESC_MGMT_BYPASS_MASK 0x1U
#define SSS_ADM_MSG_DESC_REPLY_AEQE_EN_MASK 0x1U
#define SSS_ADM_MSG_DESC_MSG_VALID_MASK 0x3U
#define SSS_ADM_MSG_DESC_MSG_CHANNEL_MASK 0x3U
#define SSS_ADM_MSG_DESC_PRIV_DATA_MASK 0xFFFFFFU
#define SSS_ADM_MSG_DESC_DEST_MASK 0x1FU
#define SSS_ADM_MSG_DESC_SIZE_MASK 0x7FFU
#define SSS_ADM_MSG_DESC_XOR_CHKSUM_MASK 0xFFU
#define SSS_ADM_MSG_DESC_SET(val, member) \
((((u64)(val)) & SSS_ADM_MSG_DESC_##member##_MASK) << \
SSS_ADM_MSG_DESC_##member##_SHIFT)
/* adm_msg_state header */
#define SSS_ADM_MSG_STATE_HEAD_VALID_SHIFT 0
#define SSS_ADM_MSG_STATE_HEAD_MSG_ID_SHIFT 16
......@@ -89,6 +38,9 @@
#define SSS_ADM_MSG_STATE_HEAD_VALID_MASK 0xFFU
#define SSS_ADM_MSG_STATE_HEAD_MSG_ID_MASK 0xFFU
#define COMPLETION_TIMEOUT_DEFAULT 1000UL
#define POLLING_COMPLETION_TIMEOUT_DEFAULT 1000U
#define SSS_ADM_MSG_STATE_HEAD_GET(val, member) \
(((val) >> SSS_ADM_MSG_STATE_HEAD_##member##_SHIFT) & \
SSS_ADM_MSG_STATE_HEAD_##member##_MASK)
......@@ -130,8 +82,6 @@ struct sss_msg_head {
u8 rsvd0[5];
};
#define SSS_ADM_MSG_AEQ_ID 2
#define SSS_MGMT_MSG_SIZE_MIN 20
#define SSS_MGMT_MSG_SIZE_STEP 16
#define SSS_MGMT_MSG_RSVD_FOR_DEV 8
......@@ -164,6 +114,36 @@ struct sss_msg_head {
SSS_SET_MSG_HEADER(func_id, SRC_GLB_FUNC_ID) | \
SSS_SET_MSG_HEADER(msg_id, MSG_ID))
#define SSSNIC_API_CMD_RESP_HEAD_VALID_SHIFT 0
#define SSSNIC_API_CMD_RESP_HEAD_STATUS_SHIFT 8
#define SSSNIC_API_CMD_RESP_HEAD_CHAIN_ID_SHIFT 16
#define SSSNIC_API_CMD_RESP_HEAD_RESP_LEN_SHIFT 24
#define SSSNIC_API_CMD_RESP_HEAD_DRIVER_PRIV_SHIFT 40
#define SSSNIC_API_CMD_RESP_HEAD_VALID_MASK 0xFF
#define SSSNIC_API_CMD_RESP_HEAD_STATUS_MASK 0xFFU
#define SSSNIC_API_CMD_RESP_HEAD_CHAIN_ID_MASK 0xFFU
#define SSSNIC_API_CMD_RESP_HEAD_RESP_LEN_MASK 0x1FFU
#define SSSNIC_API_CMD_RESP_HEAD_DRIVER_PRIV_MASK 0xFFFFFFU
#define SSSNIC_API_CMD_RESP_HEAD_VALID_CODE 0xFF
#define SSSNIC_API_CMD_RESP_HEADER_VALID(val) \
(((val) & SSSNIC_API_CMD_RESP_HEAD_VALID_MASK) == \
SSSNIC_API_CMD_RESP_HEAD_VALID_CODE)
#define SSSNIC_API_CMD_RESP_HEAD_GET(val, member) \
(((val) >> SSSNIC_API_CMD_RESP_HEAD_##member##_SHIFT) & \
SSSNIC_API_CMD_RESP_HEAD_##member##_MASK)
#define SSSNIC_API_CMD_RESP_HEAD_CHAIN_ID(val) \
(((val) >> SSSNIC_API_CMD_RESP_HEAD_CHAIN_ID_SHIFT) & \
SSSNIC_API_CMD_RESP_HEAD_CHAIN_ID_MASK)
#define SSSNIC_API_CMD_RESP_HEAD_DRIVER_PRIV(val) \
((u16)(((val) >> SSSNIC_API_CMD_RESP_HEAD_DRIVER_PRIV_SHIFT) & \
SSSNIC_API_CMD_RESP_HEAD_DRIVER_PRIV_MASK))
static u8 sss_xor_chksum_set(void *data)
{
int id;
......@@ -223,23 +203,65 @@ static void sss_dump_adm_msg_reg(struct sss_adm_msg *adm_msg)
static int sss_adm_msg_busy(struct sss_adm_msg *adm_msg)
{
adm_msg->ci = sss_chip_get_ci(adm_msg);
if (adm_msg->ci == SSS_MASK_ID(adm_msg, adm_msg->pi + 1)) {
sdk_err(SSS_TO_HWDEV(adm_msg)->dev_hdl, "Adm cmd is busy, ci = %u, pi = %u\n",
adm_msg->ci, adm_msg->pi);
sss_dump_adm_msg_reg(adm_msg);
return -EBUSY;
void *dev = SSS_TO_HWDEV(adm_msg)->dev_hdl;
struct sss_adm_msg_elem_ctx *ctx = &adm_msg->elem_ctx[adm_msg->pi];
u64 resp_header;
switch (adm_msg->msg_type) {
case SSS_ADM_MSG_MULTI_READ:
case SSS_ADM_MSG_POLL_READ:
resp_header = be64_to_cpu(ctx->reply_fmt->head);
if (ctx->state && !SSSNIC_API_CMD_RESP_HEADER_VALID(resp_header)) {
sdk_err(dev, "Context(0x%x) busy!, pi: %u, resp_header: 0x%08x%08x\n",
ctx->state, adm_msg->pi,
upper_32_bits(resp_header),
lower_32_bits(resp_header));
sss_dump_adm_msg_reg(adm_msg);
return -EBUSY;
}
break;
case SSS_ADM_MSG_POLL_WRITE:
case SSS_ADM_MSG_WRITE_TO_MGMT_MODULE:
case SSS_ADM_MSG_WRITE_ASYNC_TO_MGMT_MODULE:
adm_msg->ci = sss_chip_get_ci(adm_msg);
if (adm_msg->ci == SSS_MASK_ID(adm_msg, adm_msg->pi + 1)) {
sdk_err(dev, "API CMD chain %d is busy, cons_idx = %u, prod_idx = %u\n",
adm_msg->msg_type, adm_msg->ci,
adm_msg->pi);
sss_dump_adm_msg_reg(adm_msg);
return -EBUSY;
}
break;
default:
sdk_err(dev, "Unknown Chain type %d\n", adm_msg->msg_type);
return -EINVAL;
}
return 0;
}
static void sss_prepare_elem_ctrl(u64 *elem_ctrl)
static void sss_prepare_elem_ctrl(u64 *elem_ctrl, enum sss_adm_msg_type msg_type)
{
u64 control;
u8 chksum;
u16 elem_len = ALIGN(SSS_ADM_MSG_ELEM_DESC_SIZE +
SSS_ADM_MSG_ELEM_DATA_ADDR_SIZE, SSS_ADM_MSG_ELEM_ALIGNMENT);
u16 elem_len = 0;
switch (msg_type) {
case SSS_ADM_MSG_POLL_READ:
elem_len = ALIGN(SSS_ADM_MSG_ELEM_DESC_SIZE + SSS_ADM_MSG_ELEM_WB_ADDR_SIZE +
SSS_ADM_MSG_ELEM_DATA_ADDR_SIZE, SSS_ADM_MSG_ELEM_ALIGNMENT);
break;
case SSS_ADM_MSG_WRITE_TO_MGMT_MODULE:
case SSS_ADM_MSG_POLL_WRITE:
case SSS_ADM_MSG_WRITE_ASYNC_TO_MGMT_MODULE:
elem_len = ALIGN(SSS_ADM_MSG_ELEM_DESC_SIZE +
SSS_ADM_MSG_ELEM_DATA_ADDR_SIZE, SSS_ADM_MSG_ELEM_ALIGNMENT);
break;
default:
break;
}
control = SSS_ADM_MSG_ELEM_CTRL_SET(SSS_SIZE_TO_8B(elem_len), ELEM_LEN) |
SSS_ADM_MSG_ELEM_CTRL_SET(0ULL, RD_DMA_ATTR_OFF) |
......@@ -258,13 +280,41 @@ static void sss_prepare_elem_desc(struct sss_adm_msg *adm_msg,
{
u32 priv;
struct sss_adm_msg_elem *elem = adm_msg->now_node;
struct sss_adm_msg_elem_ctx *ctx = &adm_msg->elem_ctx[adm_msg->pi];
switch (adm_msg->msg_type) {
case SSS_ADM_MSG_POLL_READ:
priv = SSS_READ_ADM_MSG_PRIV_DATA(adm_msg->msg_type, ctx->store_pi);
elem->desc = SSS_ADM_MSG_DESC_SET(SSS_SGL_TYPE, SGL_TYPE) |
SSS_ADM_MSG_DESC_SET(SSS_ADM_MSG_READ, RD_WR) |
SSS_ADM_MSG_DESC_SET(SSS_BYPASS, MGMT_BYPASS) |
SSS_ADM_MSG_DESC_SET(SSS_NO_TRIGGER, REPLY_AEQE_EN) |
SSS_ADM_MSG_DESC_SET(priv, PRIV_DATA);
break;
case SSS_ADM_MSG_POLL_WRITE:
priv = SSS_WRITE_ADM_MSG_PRIV_DATA(adm_msg->msg_type);
elem->desc = SSS_ADM_MSG_DESC_SET(SSS_SGL_TYPE, SGL_TYPE) |
SSS_ADM_MSG_DESC_SET(SSS_ADM_MSG_WRITE, RD_WR) |
SSS_ADM_MSG_DESC_SET(SSS_BYPASS, MGMT_BYPASS) |
SSS_ADM_MSG_DESC_SET(SSS_NO_TRIGGER, REPLY_AEQE_EN) |
SSS_ADM_MSG_DESC_SET(priv, PRIV_DATA);
break;
case SSS_ADM_MSG_WRITE_ASYNC_TO_MGMT_MODULE:
case SSS_ADM_MSG_WRITE_TO_MGMT_MODULE:
priv = SSS_WRITE_ADM_MSG_PRIV_DATA(adm_msg->msg_type);
elem->desc = SSS_ADM_MSG_DESC_SET(SSS_SGL_TYPE, SGL_TYPE) |
SSS_ADM_MSG_DESC_SET(SSS_ADM_MSG_WRITE, RD_WR) |
SSS_ADM_MSG_DESC_SET(SSS_NO_BYPASS, MGMT_BYPASS) |
SSS_ADM_MSG_DESC_SET(SSS_TRIGGER, REPLY_AEQE_EN) |
SSS_ADM_MSG_DESC_SET(priv, PRIV_DATA);
break;
default:
sdk_err(((struct sss_hwdev *)adm_msg->hwdev)->dev_hdl, "Unknown Chain type: %d\n",
adm_msg->msg_type);
return;
}
priv = SSS_WRITE_ADM_MSG_PRIV_DATA(adm_msg->msg_type);
elem->desc = SSS_ADM_MSG_DESC_SET(SSS_SGL_TYPE, SGL_TYPE) |
SSS_ADM_MSG_DESC_SET(SSS_ADM_MSG_WRITE, RD_WR) |
SSS_ADM_MSG_DESC_SET(SSS_NO_BYPASS, MGMT_BYPASS) |
SSS_ADM_MSG_DESC_SET(SSS_TRIGGER, REPLY_AEQE_EN) |
SSS_ADM_MSG_DESC_SET(priv, PRIV_DATA);
elem->desc |= SSS_ADM_MSG_DESC_SET(SSS_ADM_MSG_CHANNEL_0, MSG_CHANNEL) |
SSS_ADM_MSG_DESC_SET(SSS_VALID_MSG_CHANNEL, MSG_VALID);
......@@ -291,7 +341,7 @@ static void sss_prepare_elem(struct sss_adm_msg *adm_msg, u8 node_id,
{
struct sss_adm_msg_elem *now_node = adm_msg->now_node;
sss_prepare_elem_ctrl(&now_node->control);
sss_prepare_elem_ctrl(&now_node->control, adm_msg->msg_type);
sss_prepare_elem_desc(adm_msg, node_id, cmd_size);
sss_prepare_elem_ctx(adm_msg, cmd, cmd_size);
}
......@@ -345,21 +395,87 @@ static enum sss_process_ret sss_wait_for_state_poll_handler(void *priv_data)
return SSS_PROCESS_DOING;
}
static enum sss_process_ret check_cmd_resp_handler(void *priv_data)
{
struct sss_adm_msg_elem_ctx *ctxt = priv_data;
u64 resp_header;
u8 resp_status;
if (!SSS_TO_HWDEV(ctxt)->chip_present_flag) {
pr_err("Fail to resp chip present");
return SSS_PROCESS_ERR;
}
resp_header = be64_to_cpu(ctxt->reply_fmt->head);
rmb(); /* read the latest header */
if (SSSNIC_API_CMD_RESP_HEADER_VALID(resp_header)) {
resp_status = SSSNIC_API_CMD_RESP_HEAD_GET(resp_header, STATUS);
if (resp_status) {
pr_err("Api chain response data err, status: %u\n",
resp_status);
return SSS_PROCESS_ERR;
}
return SSS_PROCESS_OK;
}
return SSS_PROCESS_DOING;
}
static int sss_wait_for_state_poll(struct sss_adm_msg *adm_msg)
{
return sss_check_handler_timeout(adm_msg, sss_wait_for_state_poll_handler,
SSS_ADM_MSG_STATE_TIMEOUT, 100); /* wait 100 us once */
}
static int wait_for_resp_polling(struct sss_adm_msg_elem_ctx *ctx)
{
return sss_check_handler_timeout(ctx, check_cmd_resp_handler,
POLLING_COMPLETION_TIMEOUT_DEFAULT,
USEC_PER_MSEC);
}
static void copy_resp_data(struct sss_adm_msg_elem_ctx *ctx, void *ack,
u16 ack_size)
{
struct sss_adm_msg_reply_fmt *resp = ctx->reply_fmt;
memcpy(ack, &resp->reply, ack_size);
ctx->state = 0;
}
static int sss_wait_for_adm_msg_completion(struct sss_adm_msg *adm_msg,
struct sss_adm_msg_elem_ctx *ctx)
struct sss_adm_msg_elem_ctx *ctx,
void *ack, u16 ack_size)
{
int ret = 0;
ret = sss_wait_for_state_poll(adm_msg);
if (ret != 0) {
sdk_err(SSS_TO_HWDEV(adm_msg)->dev_hdl, "Adm msg poll state timeout\n");
switch (adm_msg->msg_type) {
case SSS_ADM_MSG_POLL_READ:
ret = wait_for_resp_polling(ctx);
if (ret == 0)
copy_resp_data(ctx, ack, ack_size);
else
sdk_err(SSS_TO_HWDEV(adm_msg)->dev_hdl, "API CMD poll response timeout\n");
break;
case SSS_ADM_MSG_POLL_WRITE:
case SSS_ADM_MSG_WRITE_TO_MGMT_MODULE:
ret = sss_wait_for_state_poll(adm_msg);
break;
case SSS_ADM_MSG_WRITE_ASYNC_TO_MGMT_MODULE:
/* No need to wait */
break;
default:
sdk_err(SSS_TO_HWDEV(adm_msg)->dev_hdl, "Unknown API CMD Chain type: %d\n",
adm_msg->msg_type);
ret = -EINVAL;
}
if (ret) {
sss_dump_adm_msg_reg(adm_msg);
sdk_err(SSS_TO_HWDEV(adm_msg)->dev_hdl, "Adm msg wait timeout,type :%d\n",
adm_msg->msg_type);
}
return ret;
......@@ -381,25 +497,25 @@ static inline void sss_update_adm_msg_ctx(struct sss_adm_msg *adm_msg)
static void sss_adm_msg_lock(struct sss_adm_msg *adm_msg)
{
down(&adm_msg->sem);
if (adm_msg->msg_type == SSS_ADM_MSG_WRITE_ASYNC_TO_MGMT_MODULE)
spin_lock(&adm_msg->async_lock);
else
down(&adm_msg->sem);
}
static void sss_adm_msg_unlock(struct sss_adm_msg *adm_msg)
{
up(&adm_msg->sem);
if (adm_msg->msg_type == SSS_ADM_MSG_WRITE_ASYNC_TO_MGMT_MODULE)
spin_unlock(&adm_msg->async_lock);
else
up(&adm_msg->sem);
}
static int sss_send_adm_cmd(struct sss_adm_msg *adm_msg, u8 node_id,
const void *cmd, u16 cmd_size)
static int sss_adm_msg_io(struct sss_adm_msg *adm_msg, u8 node_id,
const void *cmd, u16 cmd_size, void *ack, u16 ack_size)
{
struct sss_adm_msg_elem_ctx *ctx = NULL;
if (adm_msg->msg_type != SSS_ADM_MSG_WRITE_TO_MGMT_MODULE) {
sdk_err(SSS_TO_HWDEV(adm_msg)->dev_hdl,
"Unsupport adm cmd type: %d\n", adm_msg->msg_type);
return -EINVAL;
}
sss_adm_msg_lock(adm_msg);
ctx = &adm_msg->elem_ctx[adm_msg->pi];
......@@ -423,7 +539,19 @@ static int sss_send_adm_cmd(struct sss_adm_msg *adm_msg, u8 node_id,
sss_adm_msg_unlock(adm_msg);
return sss_wait_for_adm_msg_completion(adm_msg, ctx);
return sss_wait_for_adm_msg_completion(adm_msg, ctx, ack, ack_size);
}
int sss_adm_msg_write(struct sss_adm_msg *adm_msg, u8 node_id,
const void *cmd, u16 cmd_size)
{
return sss_adm_msg_io(adm_msg, node_id, cmd, cmd_size, NULL, 0);
}
int sss_adm_msg_read(struct sss_adm_msg *adm_msg, u8 node_id,
const void *cmd, u16 size, void *ack, u16 ack_size)
{
return sss_adm_msg_io(adm_msg, node_id, cmd, size, ack, ack_size);
}
static void sss_set_adm_event_flag(struct sss_msg_pf_to_mgmt *pf_to_mgmt,
......@@ -464,15 +592,61 @@ static void sss_encapsulate_adm_msg(u8 *adm_msg, u64 *header,
memcpy(adm_msg_new, body, (size_t)(u32)body_len);
}
#define SSS_MAX_PF_MGMT_BUF_MAX 2048L
int sss_adm_msg_read_ack(void *hwdev, u8 dest, const void *cmd,
u16 size, void *ack, u16 ack_size)
{
struct sss_msg_pf_to_mgmt *pf_to_mgmt = NULL;
struct sss_adm_msg *adm_mag = NULL;
if (!hwdev || !cmd || (ack_size && !ack) || size > SSS_MAX_PF_MGMT_BUF_MAX)
return -EINVAL;
if (!SSS_SUPPORT_ADM_MSG((struct sss_hwdev *)hwdev))
return -EPERM;
pf_to_mgmt = ((struct sss_hwdev *)hwdev)->pf_to_mgmt;
adm_mag = pf_to_mgmt->adm_msg[SSS_ADM_MSG_POLL_READ];
if (!(((struct sss_hwdev *)hwdev)->chip_present_flag))
return -EPERM;
return sss_adm_msg_read(adm_mag, dest, cmd, size, ack, ack_size);
}
int sss_adm_msg_write_nack(void *hwdev, u8 dest, const void *cmd, u16 size)
{
struct sss_msg_pf_to_mgmt *pf_to_mgmt = NULL;
struct sss_adm_msg *adm_mag = NULL;
if (!hwdev || !size || !cmd || size > SSS_MAX_PF_MGMT_BUF_MAX)
return -EINVAL;
if (!SSS_SUPPORT_ADM_MSG((struct sss_hwdev *)hwdev))
return -EPERM;
pf_to_mgmt = ((struct sss_hwdev *)hwdev)->pf_to_mgmt;
adm_mag = pf_to_mgmt->adm_msg[SSS_ADM_MSG_POLL_WRITE];
if (!(((struct sss_hwdev *)hwdev)->chip_present_flag))
return -EPERM;
return sss_adm_msg_write(adm_mag, dest, cmd, size);
}
#define SSS_MSG_NO_RESP 0xFFFF
static int sss_send_adm_msg(struct sss_msg_pf_to_mgmt *pf_to_mgmt,
u8 mod, u16 cmd, const void *msg_body, u16 msg_body_len)
{
struct sss_hwif *hwif = SSS_TO_HWDEV(pf_to_mgmt)->hwif;
void *adm_msg = pf_to_mgmt->sync_buf;
void *msg_buf = pf_to_mgmt->sync_buf;
u16 adm_msg_len = sss_align_adm_msg_len(msg_body_len);
u32 func_id = SSS_GET_HWIF_GLOBAL_ID(hwif);
u8 node_id = SSS_MGMT_CPU_NODE_ID(SSS_TO_HWDEV(pf_to_mgmt));
u64 header;
struct sss_adm_msg *adm_mag;
if (sss_get_dev_present_flag(pf_to_mgmt->hwdev) == 0)
return -EFAULT;
......@@ -481,13 +655,15 @@ static int sss_send_adm_msg(struct sss_msg_pf_to_mgmt *pf_to_mgmt,
return -EFAULT;
sss_set_adm_event_flag(pf_to_mgmt, SSS_ADM_EVENT_START);
SSS_INCREASE_SYNC_MSG_ID(pf_to_mgmt);
header = SSS_ENCAPSULATE_ADM_MSG_HEAD(func_id, msg_body_len, mod,
cmd, SSS_SYNC_MSG_ID(pf_to_mgmt));
sss_encapsulate_adm_msg((u8 *)adm_msg, &header, msg_body, msg_body_len);
cmd, SSS_INCREASE_SYNC_MSG_ID(pf_to_mgmt));
sss_encapsulate_adm_msg((u8 *)msg_buf, &header, msg_body, msg_body_len);
adm_mag = pf_to_mgmt->adm_msg[SSS_ADM_MSG_WRITE_TO_MGMT_MODULE];
return sss_send_adm_cmd(&pf_to_mgmt->adm_msg, node_id, adm_msg, adm_msg_len);
return sss_adm_msg_write(adm_mag, node_id, msg_buf, adm_msg_len);
}
static inline void sss_check_msg_body(u8 mod, void *buf_in)
......
......@@ -5,6 +5,10 @@
#define SSS_HWIF_ADM_H
#include <linux/types.h>
int sss_adm_msg_read_ack(void *hwdev, u8 dest, const void *cmd,
u16 size, void *ack, u16 ack_size);
int sss_adm_msg_write_nack(void *hwdev, u8 dest, const void *cmd, u16 size);
int sss_sync_send_adm_msg(void *hwdev, u8 mod, u16 cmd, void *buf_in,
u16 in_size, void *buf_out, u16 *out_size, u32 timeout);
......
......@@ -4,6 +4,19 @@
#ifndef SSS_HWIF_ADM_COMMON_H
#define SSS_HWIF_ADM_COMMON_H
#define SSS_ADM_MSG_AEQ_ID 2
#define SSS_WRITE_ADM_MSG_PRIV_DATA(id) (((u8)(id)) << 16)
#define SSS_READ_ADM_MSG_PRIV_DATA(id, token) ((((u32)(id)) << 16) + (token))
#define SSS_MASK_ID(adm_msg, id) \
((id) & ((adm_msg)->elem_num - 1))
#define SSS_SIZE_TO_4B(size) \
(ALIGN((u32)(size), 4U) >> 2)
#define SSS_SIZE_TO_8B(size) \
(ALIGN((u32)(size), 8U) >> 3)
/* ADM_STATUS_0 CSR: 0x0030+adm msg id*0x080 */
#define SSS_ADM_MSG_STATE_CI_MASK 0xFFFFFFU
#define SSS_ADM_MSG_STATE_CI_SHIFT 0
......@@ -20,4 +33,47 @@
#define SSS_GET_ADM_MSG_STATE(val, member) \
(((val) >> SSS_ADM_MSG_STATE_##member##_SHIFT) & \
SSS_ADM_MSG_STATE_##member##_MASK)
/* adm_msg_elem.desc structure */
#define SSS_ADM_MSG_DESC_SGL_TYPE_SHIFT 0
#define SSS_ADM_MSG_DESC_RD_WR_SHIFT 1
#define SSS_ADM_MSG_DESC_MGMT_BYPASS_SHIFT 2
#define SSS_ADM_MSG_DESC_REPLY_AEQE_EN_SHIFT 3
#define SSS_ADM_MSG_DESC_MSG_VALID_SHIFT 4
#define SSS_ADM_MSG_DESC_MSG_CHANNEL_SHIFT 6
#define SSS_ADM_MSG_DESC_PRIV_DATA_SHIFT 8
#define SSS_ADM_MSG_DESC_DEST_SHIFT 32
#define SSS_ADM_MSG_DESC_SIZE_SHIFT 40
#define SSS_ADM_MSG_DESC_XOR_CHKSUM_SHIFT 56
#define SSS_ADM_MSG_DESC_SGL_TYPE_MASK 0x1U
#define SSS_ADM_MSG_DESC_RD_WR_MASK 0x1U
#define SSS_ADM_MSG_DESC_MGMT_BYPASS_MASK 0x1U
#define SSS_ADM_MSG_DESC_REPLY_AEQE_EN_MASK 0x1U
#define SSS_ADM_MSG_DESC_MSG_VALID_MASK 0x3U
#define SSS_ADM_MSG_DESC_MSG_CHANNEL_MASK 0x3U
#define SSS_ADM_MSG_DESC_PRIV_DATA_MASK 0xFFFFFFU
#define SSS_ADM_MSG_DESC_DEST_MASK 0x1FU
#define SSS_ADM_MSG_DESC_SIZE_MASK 0x7FFU
#define SSS_ADM_MSG_DESC_XOR_CHKSUM_MASK 0xFFU
#define SSS_ADM_MSG_DESC_SET(val, member) \
((((u64)(val)) & SSS_ADM_MSG_DESC_##member##_MASK) << \
SSS_ADM_MSG_DESC_##member##_SHIFT)
/* adm_msg_elem structure */
#define SSS_ADM_MSG_ELEM_CTRL_ELEM_LEN_SHIFT 0
#define SSS_ADM_MSG_ELEM_CTRL_RD_DMA_ATTR_OFF_SHIFT 16
#define SSS_ADM_MSG_ELEM_CTRL_WR_DMA_ATTR_OFF_SHIFT 24
#define SSS_ADM_MSG_ELEM_CTRL_XOR_CHKSUM_SHIFT 56
#define SSS_ADM_MSG_ELEM_CTRL_ELEM_LEN_MASK 0x3FU
#define SSS_ADM_MSG_ELEM_CTRL_RD_DMA_ATTR_OFF_MASK 0x3FU
#define SSS_ADM_MSG_ELEM_CTRL_WR_DMA_ATTR_OFF_MASK 0x3FU
#define SSS_ADM_MSG_ELEM_CTRL_XOR_CHKSUM_MASK 0xFFU
#define SSS_ADM_MSG_ELEM_CTRL_SET(val, member) \
((((u64)(val)) & SSS_ADM_MSG_ELEM_CTRL_##member##_MASK) << \
SSS_ADM_MSG_ELEM_CTRL_##member##_SHIFT)
#endif
......@@ -310,9 +310,28 @@ static void sss_init_ctx_buf_reply_addr(struct sss_adm_msg *adm_msg,
elem->read.hw_msg_paddr = cpu_to_be64(buf_paddr);
}
static void sss_alloc_reply_buf(struct sss_adm_msg *adm_msg,
struct sss_adm_msg_elem *elem, u32 cell_idx)
{
struct sss_adm_msg_elem_ctx *ctx = NULL;
void *resp_vaddr;
u64 resp_paddr;
resp_vaddr = (u8 *)((u64)adm_msg->reply_vaddr_base +
adm_msg->reply_size_align * cell_idx);
resp_paddr = adm_msg->reply_paddr_base +
adm_msg->reply_size_align * cell_idx;
ctx = &adm_msg->elem_ctx[cell_idx];
ctx->reply_fmt = resp_vaddr;
elem->read.hw_wb_reply_paddr = cpu_to_be64(resp_paddr);
}
static int sss_init_elem_ctx(struct sss_adm_msg *adm_msg, u32 elem_id)
{
struct sss_adm_msg_elem_ctx *ctx = NULL;
struct sss_adm_msg_elem *elem;
sss_alloc_elem_buf_handler_t handler[] = {
NULL,
NULL,
......@@ -322,6 +341,11 @@ static int sss_init_elem_ctx(struct sss_adm_msg *adm_msg, u32 elem_id)
sss_init_ctx_buf_reply_addr,
sss_init_ctx_buf_addr
};
elem = (struct sss_adm_msg_elem *)SSS_GET_ADM_MSG_ELEM_VADDR(adm_msg, elem_id);
if (adm_msg->msg_type == SSS_ADM_MSG_MULTI_READ ||
adm_msg->msg_type == SSS_ADM_MSG_POLL_READ)
sss_alloc_reply_buf(adm_msg, elem, elem_id);
ctx = &adm_msg->elem_ctx[elem_id];
ctx->elem_vaddr =
......@@ -379,17 +403,6 @@ static int sss_init_adm_msg_elem(struct sss_adm_msg *adm_msg)
return 0;
}
static void sss_init_adm_msg_param(struct sss_adm_msg *adm_msg,
struct sss_hwdev *hwdev)
{
adm_msg->hwdev = hwdev;
adm_msg->elem_num = SSS_ADM_MSG_ELEM_NUM;
adm_msg->reply_size = SSS_ADM_MSG_REPLY_DATA_SIZE;
adm_msg->elem_size = SSS_ADM_MSG_ELEM_SIZE;
adm_msg->msg_type = SSS_ADM_MSG_WRITE_TO_MGMT_MODULE;
sema_init(&adm_msg->sem, 1);
}
static int sss_alloc_adm_msg_ctx(struct sss_adm_msg *adm_msg)
{
size_t ctx_size;
......@@ -512,46 +525,105 @@ static void sss_free_adm_msg_buf(struct sss_adm_msg *adm_msg)
sss_free_adm_msg_ctx(adm_msg);
}
static int sss_init_adm_msg(struct sss_hwdev *hwdev,
struct sss_adm_msg *adm_msg)
static void sss_init_adm_msg_param(struct sss_adm_msg *adm_msg,
struct sss_hwdev *hwdev, u8 msg_type)
{
adm_msg->hwdev = hwdev;
adm_msg->elem_num = SSS_ADM_MSG_ELEM_NUM;
adm_msg->reply_size = SSS_ADM_MSG_REPLY_DATA_SIZE;
adm_msg->elem_size = SSS_ADM_MSG_ELEM_SIZE;
adm_msg->msg_type = msg_type;
adm_msg->pi = 0;
adm_msg->ci = 0;
if (adm_msg->msg_type == SSS_ADM_MSG_WRITE_ASYNC_TO_MGMT_MODULE)
spin_lock_init(&adm_msg->async_lock);
else
sema_init(&adm_msg->sem, 1);
}
static int create_adm_msg(struct sss_hwdev *hwdev, struct sss_adm_msg **adm_msg, u8 msg_type)
{
struct sss_adm_msg *msg;
int ret;
if (!SSS_SUPPORT_ADM_MSG(hwdev))
return 0;
msg = kzalloc(sizeof(*msg), GFP_KERNEL);
if (!msg)
return -ENOMEM;
sss_init_adm_msg_param(adm_msg, hwdev);
sss_init_adm_msg_param(msg, hwdev, msg_type);
ret = sss_alloc_adm_msg_buf(adm_msg);
ret = sss_alloc_adm_msg_buf(msg);
if (ret != 0) {
sdk_err(hwdev->dev_hdl, "Fail to init adm msg buf\n");
return ret;
}
ret = sss_init_adm_msg_elem(adm_msg);
ret = sss_init_adm_msg_elem(msg);
if (ret != 0) {
sdk_err(hwdev->dev_hdl, "Fail to init adm msg elem\n");
sss_free_adm_msg_buf(adm_msg);
sss_free_adm_msg_buf(msg);
return ret;
}
ret = sss_chip_init_adm_msg(adm_msg);
ret = sss_chip_init_adm_msg(msg);
if (ret != 0) {
sdk_err(hwdev->dev_hdl, "Fail to init adm msg\n");
sss_free_adm_msg_buf(adm_msg);
sss_free_adm_msg_buf(msg);
return ret;
}
*adm_msg = msg;
return 0;
}
void sss_destroy_adm_msg(struct sss_adm_msg *adm_msg)
{
sss_free_adm_msg_buf(adm_msg);
kfree(adm_msg);
}
static int sss_init_adm_msg(struct sss_hwdev *hwdev,
struct sss_adm_msg **adm_msg)
{
int ret;
u8 i;
u8 adm_msg_type;
void *dev = ((struct sss_hwdev *)hwdev)->dev_hdl;
if (!SSS_SUPPORT_ADM_MSG(hwdev))
return 0;
for (adm_msg_type = SSS_ADM_MSG_WRITE_TO_MGMT_MODULE;
adm_msg_type < SSS_ADM_MSG_MAX; adm_msg_type++) {
ret = create_adm_msg(hwdev, &adm_msg[adm_msg_type], adm_msg_type);
if (ret) {
sdk_err(dev, "Failed to create adm msg %d\n", adm_msg_type);
goto create_adm_msg_err;
}
}
return 0;
create_adm_msg_err:
for (i = SSS_ADM_MSG_WRITE_TO_MGMT_MODULE; i < adm_msg_type; i++)
sss_destroy_adm_msg(hwdev->pf_to_mgmt->adm_msg[adm_msg_type]);
return ret;
}
static void sss_deinit_adm_msg(const struct sss_hwdev *hwdev,
struct sss_adm_msg *adm_msg)
struct sss_adm_msg **adm_msg)
{
u8 adm_msg_type;
if (!SSS_SUPPORT_ADM_MSG(hwdev))
return;
sss_free_adm_msg_buf(adm_msg);
for (adm_msg_type = SSS_ADM_MSG_WRITE_TO_MGMT_MODULE;
adm_msg_type < SSS_ADM_MSG_MAX; adm_msg_type++)
sss_destroy_adm_msg(adm_msg[adm_msg_type]);
}
static int sss_alloc_msg_buf(struct sss_msg_pf_to_mgmt *mgmt_msg)
......@@ -578,8 +650,15 @@ static int sss_alloc_msg_buf(struct sss_msg_pf_to_mgmt *mgmt_msg)
if (!mgmt_msg->sync_buf)
goto alloc_sync_buf_err;
mgmt_msg->async_msg_buf = kzalloc(SSS_PF_MGMT_BUF_LEN_MAX, GFP_KERNEL);
if (!mgmt_msg->async_msg_buf)
goto alloc_async_msg_buf_err;
return 0;
alloc_async_msg_buf_err:
kfree(mgmt_msg->sync_buf);
mgmt_msg->sync_buf = NULL;
alloc_sync_buf_err:
kfree(mgmt_msg->ack_buf);
mgmt_msg->ack_buf = NULL;
......@@ -600,6 +679,7 @@ static void sss_free_msg_buf(struct sss_msg_pf_to_mgmt *mgmt_msg)
struct sss_recv_msg *recv_msg = &mgmt_msg->recv_msg;
struct sss_recv_msg *resp_msg = &mgmt_msg->recv_resp_msg;
kfree(mgmt_msg->async_msg_buf);
kfree(mgmt_msg->sync_buf);
kfree(mgmt_msg->ack_buf);
kfree(resp_msg->buf);
......@@ -615,6 +695,7 @@ int sss_hwif_init_adm(struct sss_hwdev *hwdev)
if (!mgmt_msg)
return -ENOMEM;
spin_lock_init(&mgmt_msg->async_msg_lock);
spin_lock_init(&mgmt_msg->sync_event_lock);
sema_init(&mgmt_msg->sync_lock, 1);
mgmt_msg->hwdev = hwdev;
......@@ -633,7 +714,7 @@ int sss_hwif_init_adm(struct sss_hwdev *hwdev)
goto alloc_msg_buf_err;
}
ret = sss_init_adm_msg(hwdev, &mgmt_msg->adm_msg);
ret = sss_init_adm_msg(hwdev, mgmt_msg->adm_msg);
if (ret != 0) {
sdk_err(hwdev->dev_hdl, "Fail to init adm msg\n");
goto init_all_adm_err;
......@@ -660,7 +741,7 @@ void sss_hwif_deinit_adm(struct sss_hwdev *hwdev)
destroy_workqueue(mgmt_msg->workq);
sss_deinit_adm_msg(hwdev, &mgmt_msg->adm_msg);
sss_deinit_adm_msg(hwdev, mgmt_msg->adm_msg);
sss_free_msg_buf(mgmt_msg);
......
......@@ -261,7 +261,7 @@ struct sss_ctrlq_wqe {
};
};
typedef void (*sss_ctrlq_type_handler_t)(struct sss_ctrlq *ctrlq,
typedef int (*sss_ctrlq_type_handler_t)(struct sss_ctrlq *ctrlq,
struct sss_ctrlq_wqe *wqe, u16 ci);
void *sss_ctrlq_read_wqe(struct sss_wq *wq, u16 *ci)
......@@ -801,58 +801,66 @@ static void sss_ctrlq_update_cmd_info(struct sss_ctrlq *ctrlq,
spin_unlock(&ctrlq->ctrlq_lock);
}
static void sss_ctrlq_arm_ceq_handler(struct sss_ctrlq *ctrlq,
struct sss_ctrlq_wqe *wqe, u16 ci)
static int sss_ctrlq_arm_ceq_handler(struct sss_ctrlq *ctrlq,
struct sss_ctrlq_wqe *wqe, u16 ci)
{
struct sss_wqe_ctrl *ctrl = &wqe->inline_wqe.wqe_scmd.ctrl;
u32 info = sss_hw_cpu32((ctrl)->info);
if (!SSS_WQE_COMPLETE(info))
return;
return -EBUSY;
sss_erase_wqe_complete_bit(ctrlq, wqe, ci);
return 0;
}
static void sss_ctrlq_default_handler(struct sss_ctrlq *ctrlq,
struct sss_ctrlq_wqe *wqe, u16 ci)
static int sss_ctrlq_default_handler(struct sss_ctrlq *ctrlq,
struct sss_ctrlq_wqe *wqe, u16 ci)
{
struct sss_wqe_ctrl *ctrl = &wqe->wqe_lcmd.ctrl;
u32 info = sss_hw_cpu32((ctrl)->info);
if (!SSS_WQE_COMPLETE(info))
return;
return -EBUSY;
dma_rmb();
sss_ctrlq_update_cmd_info(ctrlq, wqe, ci);
sss_free_ctrlq_cmd_buf(SSS_TO_HWDEV(ctrlq), &ctrlq->cmd_info[ci]);
sss_erase_wqe_complete_bit(ctrlq, wqe, ci);
return 0;
}
static void sss_ctrlq_async_cmd_handler(struct sss_ctrlq *ctrlq,
struct sss_ctrlq_wqe *wqe, u16 ci)
static int sss_ctrlq_async_cmd_handler(struct sss_ctrlq *ctrlq,
struct sss_ctrlq_wqe *wqe, u16 ci)
{
struct sss_wqe_ctrl *ctrl = &wqe->wqe_lcmd.ctrl;
u32 info = sss_hw_cpu32((ctrl)->info);
if (!SSS_WQE_COMPLETE(info))
return;
return -EBUSY;
dma_rmb();
sss_free_ctrlq_cmd_buf(SSS_TO_HWDEV(ctrlq), &ctrlq->cmd_info[ci]);
sss_erase_wqe_complete_bit(ctrlq, wqe, ci);
return 0;
}
static void sss_ctrlq_pseudo_timeout_handler(struct sss_ctrlq *ctrlq,
struct sss_ctrlq_wqe *wqe, u16 ci)
static int sss_ctrlq_pseudo_timeout_handler(struct sss_ctrlq *ctrlq,
struct sss_ctrlq_wqe *wqe, u16 ci)
{
sss_free_ctrlq_cmd_buf(SSS_TO_HWDEV(ctrlq), &ctrlq->cmd_info[ci]);
sss_erase_wqe_complete_bit(ctrlq, wqe, ci);
return 0;
}
static void sss_ctrlq_timeout_handler(struct sss_ctrlq *ctrlq,
struct sss_ctrlq_wqe *wqe, u16 ci)
static int sss_ctrlq_timeout_handler(struct sss_ctrlq *ctrlq,
struct sss_ctrlq_wqe *wqe, u16 ci)
{
u32 i;
u32 *data = (u32 *)wqe;
......@@ -868,17 +876,20 @@ static void sss_ctrlq_timeout_handler(struct sss_ctrlq *ctrlq,
sss_free_ctrlq_cmd_buf(SSS_TO_HWDEV(ctrlq), &ctrlq->cmd_info[ci]);
sss_erase_wqe_complete_bit(ctrlq, wqe, ci);
return 0;
}
static void sss_ctrlq_force_stop_handler(struct sss_ctrlq *ctrlq,
struct sss_ctrlq_wqe *wqe, u16 ci)
static int sss_ctrlq_force_stop_handler(struct sss_ctrlq *ctrlq,
struct sss_ctrlq_wqe *wqe, u16 ci)
{
sss_ctrlq_async_cmd_handler(ctrlq, wqe, ci);
return sss_ctrlq_async_cmd_handler(ctrlq, wqe, ci);
}
void sss_ctrlq_ceq_handler(void *dev, u32 data)
{
u16 ci;
int ret;
enum sss_ctrlq_type type = SSS_GET_CEQE_CTRLQ(data, TYPE);
struct sss_ctrlq *ctrlq = &SSS_TO_CTRLQ_INFO(dev)->ctrlq[type];
struct sss_ctrlq_wqe *ctrlq_wqe = NULL;
......@@ -895,17 +906,23 @@ void sss_ctrlq_ceq_handler(void *dev, u32 data)
sss_ctrlq_force_stop_handler,
};
ctrlq_wqe = sss_ctrlq_read_wqe(&ctrlq->wq, &ci);
if (!ctrlq_wqe)
return;
while ((ctrlq_wqe = sss_ctrlq_read_wqe(&ctrlq->wq, &ci)) != NULL) {
info = &ctrlq->cmd_info[ci];
info = &ctrlq->cmd_info[ci];
if (info->msg_type < SSS_MSG_TYPE_NONE ||
info->msg_type >= SSS_MSG_TYPE_MAX) {
sss_ctrlq_default_handler(ctrlq, ctrlq_wqe, ci);
return;
}
if (info->msg_type < SSS_MSG_TYPE_NONE ||
info->msg_type >= SSS_MSG_TYPE_MAX) {
ret = sss_ctrlq_default_handler(ctrlq, ctrlq_wqe, ci);
if (ret)
break;
continue;
}
if (!handler[info->msg_type])
break;
if (handler[info->msg_type])
handler[info->msg_type](ctrlq, ctrlq_wqe, ci);
ret = handler[info->msg_type](ctrlq, ctrlq_wqe, ci);
if (ret)
break;
}
}
......@@ -119,6 +119,15 @@ enum sss_func_type sss_get_func_type(void *hwdev)
}
EXPORT_SYMBOL(sss_get_func_type);
enum sss_func_type sss_get_func_id(void *hwdev)
{
if (!hwdev)
return 0;
return SSS_GET_FUNC_ID((struct sss_hwdev *)hwdev);
}
EXPORT_SYMBOL(sss_get_func_id);
u16 sss_get_glb_pf_vf_offset(void *hwdev)
{
if (!hwdev)
......
......@@ -18,6 +18,7 @@
#include "sss_hwif_mbx.h"
#include "sss_csr.h"
#include "sss_common.h"
#include "sss_adapter_mgmt.h"
#define SSS_MBX_WB_STATUS_SIZE 16UL
......@@ -25,8 +26,6 @@
#define SSS_MBX_WQ_NAME "sss_mbx"
#define SSS_MAX_FUNC 4096
#define SSS_MBX_AREA(hwif) \
((hwif)->cfg_reg_base + SSS_HW_CSR_MBX_DATA_OFF)
......@@ -449,18 +448,21 @@ int sss_hwif_init_mbx(struct sss_hwdev *hwdev)
void sss_hwif_deinit_mbx(struct sss_hwdev *hwdev)
{
struct sss_mbx *mdx = hwdev->mbx;
struct sss_mbx *mbx = hwdev->mbx;
destroy_workqueue(mdx->workq);
mdx->workq = NULL;
destroy_workqueue(mbx->workq);
mbx->workq = NULL;
sss_chip_reset_mbx_attr(mdx);
sss_chip_reset_mbx_attr(mbx);
sss_free_host_msg(mdx);
sss_free_host_msg(mbx);
sss_deinit_func_mbx_msg(mdx);
sss_deinit_func_mbx_msg(mbx);
sss_deinit_mbx_info(mdx);
sss_deinit_mbx_info(mbx);
kfree(mbx);
hwdev->mbx = NULL;
}
static bool sss_check_mbx_msg_header(void *dev_hdl,
......@@ -725,7 +727,7 @@ static void sss_recv_mbx_handler(struct sss_mbx *mbx,
int ret = 0;
void *resp_buf = recv_mbx->resp_buf;
u16 size = SSS_MBX_DATA_SIZE;
u16 src_func_id;
u16 src_func_id = recv_mbx->src_func_id;
struct sss_hwdev *hwdev = SSS_TO_HWDEV(mbx);
if (SSS_IS_VF(hwdev)) {
......@@ -733,7 +735,6 @@ static void sss_recv_mbx_handler(struct sss_mbx *mbx,
goto out;
}
src_func_id = recv_mbx->src_func_id;
if (SSS_SRC_IS_PF_OR_PPF(hwdev, src_func_id)) {
if (SSS_IS_PPF(hwdev))
ret = sss_recv_ppf_mbx_handler(mbx, recv_mbx,
......
......@@ -28,7 +28,7 @@ static void sss_record_pcie_error(void *dev)
{
struct sss_hwdev *hwdev = (struct sss_hwdev *)dev;
atomic_inc(&hwdev->hw_stats.sss_fault_event_stats.pcie_fault_stats);
atomic_inc(&hwdev->hw_stats.fault_event_stats.pcie_fault_stats);
}
pci_ers_result_t sss_detect_pci_error(struct pci_dev *pdev,
......
......@@ -26,6 +26,7 @@
#include "sss_hwdev_api.h"
#include "sss_pci_remove.h"
#include "sss_pci_global.h"
#include "sss_tool.h"
#define SSS_SYNC_YEAR_OFFSET 1900
#define SSS_SYNC_MONTH_OFFSET 1
......@@ -448,6 +449,15 @@ static int sss_init_function(struct pci_dev *pdev, struct sss_pci_adapter *adapt
sss_sync_time_to_chip(adapter);
}
sss_chip_node_lock();
ret = sss_tool_init(adapter->hwdev, adapter->chip_node);
if (ret) {
sss_chip_node_unlock();
sdk_err(&pdev->dev, "Failed to initialize dbgtool\n");
goto nictool_init_err;
}
sss_chip_node_unlock();
sss_add_func_list(adapter);
ret = sss_attach_uld_dev(adapter);
......@@ -461,6 +471,10 @@ static int sss_init_function(struct pci_dev *pdev, struct sss_pci_adapter *adapt
attach_uld_err:
sss_del_func_list(adapter);
sss_chip_node_lock();
sss_tool_uninit(adapter->hwdev, adapter->chip_node);
sss_chip_node_unlock();
nictool_init_err:
sss_unregister_dev_event(adapter->hwdev);
sss_deinit_hwdev(adapter->hwdev);
......
......@@ -26,6 +26,7 @@
#include "sss_hwdev_api.h"
#include "sss_hwif_mgmt_init.h"
#include "sss_pci_global.h"
#include "sss_tool.h"
#define SSS_WAIT_SRIOV_CFG_TIMEOUT 15000
#define SSS_EVENT_PROCESS_TIMEOUT 10000
......@@ -185,6 +186,10 @@ void sss_deinit_function(struct pci_dev *pdev)
sss_del_func_list(adapter);
sss_chip_node_lock();
sss_tool_uninit(adapter->hwdev, adapter->chip_node);
sss_chip_node_unlock();
sss_dettach_uld_dev(adapter);
sss_unregister_dev_event(adapter->hwdev);
......
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2021 3snic Technologies Co., Ltd */
#ifndef SSSNIC_NICTOOL_H
#define SSSNIC_NICTOOL_H
#include "sss_tool_chip.h"
#include "sss_tool_sdk.h"
#include "sss_tool_sm.h"
#include "sss_tool_comm.h"
#ifndef _LLT_TEST_
#define SSS_TOOL_PAGE_ORDER (10)
#else
#define SSS_TOOL_PAGE_ORDER (1)
#endif
#define SSS_TOOL_MEM_MAP_SIZE (PAGE_SIZE * (1 << SSS_TOOL_PAGE_ORDER))
#define SSS_TOOL_CARD_MAX (64)
int sss_tool_init(void *hwdev, void *chip_node);
void sss_tool_uninit(void *hwdev, void *chip_node);
extern u64 g_card_pa[SSS_TOOL_CARD_MAX];
extern void *g_card_va[SSS_TOOL_CARD_MAX];
extern int g_card_id;
#endif
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2021 3snic Technologies Co., Ltd */
#ifndef SSS_TOOL_CHIP_H
#define SSS_TOOL_CHIP_H
#include "sss_hw.h"
#include "sss_tool_comm.h"
#include "sss_tool_hw.h"
int sss_tool_msg_to_mpu(struct sss_hal_dev *hal_dev, struct sss_tool_msg *tool_msg,
void *buf_in, u32 in_size, void *buf_out, u32 *out_size);
int sss_tool_msg_to_npu(struct sss_hal_dev *hal_dev, struct sss_tool_msg *tool_msg,
void *buf_in, u32 in_size, void *buf_out, u32 *out_size);
#endif
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2021 3snic Technologies Co., Ltd */
#ifndef SSS_TOOL_HW_H
#define SSS_TOOL_HW_H
#define SSS_TOOL_CMD_TYPE (0x18)
#define SSS_TOOL_PF_DEV_MAX 32
/* Indicates the maximum number of interrupts that can be recorded.
* Subsequent interrupts are not recorded in FFM.
*/
#define SSS_TOOL_FFM_RECORD_MAX 64
#define SSS_TOOL_PF_INFO_MAX (16)
#define SSS_TOOL_BUSINFO_LEN (32)
#define SSS_TOOL_CHIP_FAULT_SIZE (110 * 1024)
#define SSS_TOOL_DRV_BUF_SIZE_MAX 4096
/* 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 sss_tool_dbg_cmd {
SSS_TOOL_DBG_CMD_API_RD = 0,
SSS_TOOL_DBG_CMD_API_WR,
SSS_TOOL_DBG_CMD_FFM_RD,
SSS_TOOL_DBG_CMD_FFM_CLR,
SSS_TOOL_DBG_CMD_PF_DEV_INFO_GET,
SSS_TOOL_DBG_CMD_MSG_2_UP,
SSS_TOOL_DBG_CMD_FREE_MEM,
SSS_TOOL_DBG_CMD_NUM
};
enum module_name {
SSS_TOOL_MSG_TO_NPU = 1,
SSS_TOOL_MSG_TO_MPU,
SSS_TOOL_MSG_TO_SM,
SSS_TOOL_MSG_TO_HW_DRIVER,
#define SSS_TOOL_MSG_TO_SRV_DRV_BASE (SSS_TOOL_MSG_TO_HW_DRIVER + 1)
SSS_TOOL_MSG_TO_NIC_DRIVER = SSS_TOOL_MSG_TO_SRV_DRV_BASE,
SSS_TOOL_MSG_TO_OVS_DRIVER,
SSS_TOOL_MSG_TO_ROCE_DRIVER,
SSS_TOOL_MSG_TO_TOE_DRIVER,
SSS_TOOL_MSG_TO_IOE_DRIVER,
SSS_TOOL_MSG_TO_FC_DRIVER,
SSS_TOOL_MSG_TO_VBS_DRIVER,
SSS_TOOL_MSG_TO_IPSEC_DRIVER,
SSS_TOOL_MSG_TO_VIRTIO_DRIVER,
SSS_TOOL_MSG_TO_MIGRATE_DRIVER,
SSS_TOOL_MSG_TO_PPA_DRIVER,
SSS_TOOL_MSG_TO_CUSTOM_DRIVER = SSS_TOOL_MSG_TO_SRV_DRV_BASE + 11,
SSS_TOOL_MSG_TO_DRIVER_MAX = SSS_TOOL_MSG_TO_SRV_DRV_BASE + 15, /* reserved */
};
enum sss_tool_adm_msg_type {
SSS_TOOL_ADM_MSG_READ,
SSS_TOOL_ADM_MSG_WRITE
};
enum sss_tool_sm_cmd_type {
SSS_TOOL_SM_CMD_RD16 = 1,
SSS_TOOL_SM_CMD_RD32,
SSS_TOOL_SM_CMD_RD64_PAIR,
SSS_TOOL_SM_CMD_RD64,
SSS_TOOL_SM_CMD_RD32_CLEAR,
SSS_TOOL_SM_CMD_RD64_PAIR_CLEAR,
SSS_TOOL_SM_CMD_RD64_CLEAR
};
enum sss_tool_channel_type {
SSS_TOOL_CHANNEL_MBOX = 1,
SSS_TOOL_CHANNEL_ADM_MSG_BYPASS,
SSS_TOOL_CHANNEL_ADM_MSG_TO_MPU,
SSS_TOOL_CHANNEL_CLP,
};
struct sss_tool_api_cmd_rd {
u32 pf_id;
u8 dest;
u8 *cmd;
u16 size;
void *ack;
u16 ack_size;
};
struct sss_tool_api_cmd_wr {
u32 pf_id;
u8 dest;
u8 *cmd;
u16 size;
};
struct sss_tool_pf_dev_info {
u64 bar0_size;
u8 bus;
u8 slot;
u8 func;
u64 phy_addr;
};
struct sss_tool_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 sss_tool_ffm_intr_tm_info {
struct sss_tool_ffm_intr_info intr_info;
u8 times;
u8 sec;
u8 min;
u8 hour;
u8 mday;
u8 mon;
u16 year;
};
struct sss_tool_ffm_record_info {
u32 ffm_num;
u32 last_err_csr_addr;
u32 last_err_csr_value;
struct sss_tool_ffm_intr_tm_info ffm[SSS_TOOL_FFM_RECORD_MAX];
};
struct sss_tool_knl_dbg_info {
struct semaphore dbgtool_sem;
struct sss_tool_ffm_record_info *ffm;
};
struct sss_tool_msg_to_up {
u8 pf_id;
u8 mod;
u8 cmd;
void *buf_in;
u16 in_size;
void *buf_out;
u16 *out_size;
};
struct sss_tool_dbg_param {
union {
struct sss_tool_api_cmd_rd api_rd;
struct sss_tool_api_cmd_wr api_wr;
struct sss_tool_pf_dev_info *dev_info;
struct sss_tool_ffm_record_info *ffm_rd;
struct sss_tool_msg_to_up msg2up;
} param;
char chip_name[16];
};
struct sss_tool_pf {
char name[IFNAMSIZ];
char bus_info[SSS_TOOL_BUSINFO_LEN];
u32 pf_type;
};
struct sss_tool_card_info {
struct sss_tool_pf pf[SSS_TOOL_PF_INFO_MAX];
u32 pf_num;
};
struct sss_tool_pf_info {
u32 valid;
u32 pf_id;
};
struct sss_tool_cmd_chip_fault_stats {
u32 offset;
u8 chip_fault_stats[SSS_TOOL_DRV_BUF_SIZE_MAX];
};
struct sss_tool_npu_msg {
u32 mod : 8;
u32 cmd : 8;
u32 ack_type : 3;
u32 direct_resp : 1;
u32 len : 12;
};
struct sss_tool_mpu_msg {
u32 channel : 8;
u32 mod : 8;
u32 cmd : 16;
};
struct sss_tool_msg {
char device_name[IFNAMSIZ];
u32 module;
union {
u32 msg_formate; /* for driver */
struct sss_tool_npu_msg npu_cmd;
struct sss_tool_mpu_msg mpu_cmd;
};
u32 timeout; /* for mpu/npu cmd */
u32 func_id;
u32 buf_in_size;
u32 buf_out_size;
void *in_buf;
void *out_buf;
int bus_num;
u8 port_id;
u8 rsvd1[3];
u32 rsvd2[4];
};
#endif /* SSS_TOOL_HW_H */
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2021 3snic Technologies Co., Ltd */
#define pr_fmt(fmt) KBUILD_MODNAME ": [TOOL]" fmt
#include <net/sock.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/time.h>
#include "sss_adapter_mgmt.h"
#include "sss_linux_kernel.h"
#include "sss_hw.h"
#include "sss_tool_comm.h"
#include "sss_tool_hw.h"
#include "sss_tool.h"
#define SSS_TOOL_DEV_PATH "/dev/sssnic_nictool_dev"
#define SSS_TOOL_DEV_CLASS "sssnic_nictool_class"
#define SSS_TOOL_DEV_NAME "sssnic_nictool_dev"
#define SSS_TOOL_CTRLQ_BUF_SIZE_MAX 2048U
#define SSS_TOOL_MSG_IN_SIZE_MAX (2048 * 1024)
#define SSS_TOOL_MSG_OUT_SIZE_MAX (2048 * 1024)
#define SSS_TOOL_BUF_SIZE_MAX (2048 * 1024)
typedef int (*sss_tool_deal_handler_fun)(struct sss_hal_dev *hal_dev, struct sss_tool_msg *tool_msg,
void *in_buf, u32 in_len, void *out_buf, u32 *out_len);
struct sss_tool_deal_handler {
enum module_name msg_name;
sss_tool_deal_handler_fun func;
};
static int g_nictool_ref_cnt;
static dev_t g_dev_id = {0};
static struct class *g_nictool_class;
static struct cdev g_nictool_cdev;
static void *g_card_node_array[SSS_TOOL_CARD_MAX] = {0};
void *g_card_va[SSS_TOOL_CARD_MAX] = {0};
u64 g_card_pa[SSS_TOOL_CARD_MAX] = {0};
int g_card_id;
static int sss_tool_msg_to_nic(struct sss_hal_dev *hal_dev, struct sss_tool_msg *tool_msg,
void *in_buf, u32 in_len, void *out_buf, u32 *out_len)
{
int ret = -EINVAL;
void *uld_dev = NULL;
enum sss_service_type service_type;
struct sss_uld_info *uld_info = sss_get_uld_info();
service_type = tool_msg->module - SSS_TOOL_MSG_TO_SRV_DRV_BASE;
if (service_type >= SSS_SERVICE_TYPE_MAX) {
tool_err("Invalid input module id: %u\n", tool_msg->module);
return -EINVAL;
}
uld_dev = sss_get_uld_dev(hal_dev, service_type);
if (!uld_dev) {
if (tool_msg->msg_formate == SSS_TOOL_GET_DRV_VERSION)
return 0;
tool_err("Fail to get uld device\n");
return -EINVAL;
}
if (uld_info[service_type].ioctl)
ret = uld_info[service_type].ioctl(uld_dev, tool_msg->msg_formate,
in_buf, in_len, out_buf, out_len);
sss_uld_dev_put(hal_dev, service_type);
return ret;
}
void sss_tool_free_in_buf(void *hwdev, const struct sss_tool_msg *tool_msg, void *in_buf)
{
if (!in_buf)
return;
if (tool_msg->module == SSS_TOOL_MSG_TO_NPU)
sss_free_ctrlq_msg_buf(hwdev, in_buf);
else
kfree(in_buf);
}
void sss_tool_free_out_buf(void *hwdev, struct sss_tool_msg *tool_msg,
void *out_buf)
{
if (!out_buf)
return;
if (tool_msg->module == SSS_TOOL_MSG_TO_NPU &&
!tool_msg->npu_cmd.direct_resp)
sss_free_ctrlq_msg_buf(hwdev, out_buf);
else
kfree(out_buf);
}
int sss_tool_alloc_in_buf(void *hwdev, struct sss_tool_msg *tool_msg,
u32 in_len, void **in_buf)
{
void *msg_buf = NULL;
if (!in_len)
return 0;
if (tool_msg->module == SSS_TOOL_MSG_TO_NPU) {
struct sss_ctrl_msg_buf *cmd_buf = NULL;
if (in_len > SSS_TOOL_CTRLQ_BUF_SIZE_MAX) {
tool_err("Invalid ctrlq in len(%u) more than %u\n",
in_len, SSS_TOOL_CTRLQ_BUF_SIZE_MAX);
return -ENOMEM;
}
cmd_buf = sss_alloc_ctrlq_msg_buf(hwdev);
if (!cmd_buf) {
tool_err("Fail to alloc ctrlq msg buf\n");
return -ENOMEM;
}
*in_buf = (void *)cmd_buf;
cmd_buf->size = (u16)in_len;
} else {
if (in_len > SSS_TOOL_MSG_IN_SIZE_MAX) {
tool_err("Invalid in len(%u) more than %u\n",
in_len, SSS_TOOL_MSG_IN_SIZE_MAX);
return -ENOMEM;
}
msg_buf = kzalloc(in_len, GFP_KERNEL);
*in_buf = msg_buf;
}
if (!(*in_buf)) {
tool_err("Fail to alloc in buf\n");
return -ENOMEM;
}
return 0;
}
int sss_tool_alloc_out_buf(void *hwdev, struct sss_tool_msg *tool_msg,
u32 out_len, void **out_buf)
{
if (!out_len) {
tool_info("out len is 0, need not alloc buf\n");
return 0;
}
if (tool_msg->module == SSS_TOOL_MSG_TO_NPU &&
!tool_msg->npu_cmd.direct_resp) {
struct sss_ctrl_msg_buf *msg_buf = NULL;
if (out_len > SSS_TOOL_CTRLQ_BUF_SIZE_MAX) {
tool_err("Invalid ctrlq out len(%u) more than %u\n",
out_len, SSS_TOOL_CTRLQ_BUF_SIZE_MAX);
return -ENOMEM;
}
msg_buf = sss_alloc_ctrlq_msg_buf(hwdev);
*out_buf = (void *)msg_buf;
} else {
if (out_len > SSS_TOOL_MSG_OUT_SIZE_MAX) {
tool_err("Invalid out len(%u) more than %u\n",
out_len, SSS_TOOL_MSG_OUT_SIZE_MAX);
return -ENOMEM;
}
*out_buf = kzalloc(out_len, GFP_KERNEL);
}
if (!(*out_buf)) {
tool_err("Fail to alloc out buf\n");
return -ENOMEM;
}
return 0;
}
int sss_tool_copy_to_user(struct sss_tool_msg *tool_msg,
u32 out_len, void *out_buf)
{
void *out_msg = NULL;
if (tool_msg->module == SSS_TOOL_MSG_TO_NPU && !tool_msg->npu_cmd.direct_resp) {
out_msg = ((struct sss_ctrl_msg_buf *)out_buf)->buf;
if (copy_to_user(tool_msg->out_buf, out_msg, out_len))
return -EFAULT;
return 0;
}
if (copy_to_user(tool_msg->out_buf, out_buf, out_len))
return -EFAULT;
return 0;
}
static int sss_tool_alloc_buf(void *hwdev, struct sss_tool_msg *tool_msg, u32 in_len,
void **in_buf, u32 out_len, void **out_buf)
{
int ret;
ret = sss_tool_alloc_in_buf(hwdev, tool_msg, in_len, in_buf);
if (ret) {
tool_err("Fail to alloc tool msg in buf\n");
return ret;
}
if (copy_from_user(*in_buf, tool_msg->in_buf, in_len)) {
tool_err("Fail to copy tool_msg to in buf\n");
sss_tool_free_in_buf(hwdev, tool_msg, *in_buf);
return -EFAULT;
}
ret = sss_tool_alloc_out_buf(hwdev, tool_msg, out_len, out_buf);
if (ret) {
tool_err("Fail to alloc tool msg out buf\n");
goto alloc_out_buf_err;
}
return 0;
alloc_out_buf_err:
sss_tool_free_in_buf(hwdev, tool_msg, *in_buf);
return ret;
}
static void sss_tool_free_buf(void *hwdev, struct sss_tool_msg *tool_msg,
void *in_buf, void *out_buf)
{
sss_tool_free_out_buf(hwdev, tool_msg, out_buf);
sss_tool_free_in_buf(hwdev, tool_msg, in_buf);
}
const struct sss_tool_deal_handler g_deal_msg_handle[] = {
{SSS_TOOL_MSG_TO_NPU, sss_tool_msg_to_npu},
{SSS_TOOL_MSG_TO_MPU, sss_tool_msg_to_mpu},
{SSS_TOOL_MSG_TO_SM, sss_tool_msg_to_sm},
{SSS_TOOL_MSG_TO_HW_DRIVER, sss_tool_msg_to_hw},
{SSS_TOOL_MSG_TO_NIC_DRIVER, sss_tool_msg_to_nic}
};
static int sss_tool_deal_cmd(struct sss_hal_dev *hal_dev, struct sss_tool_msg *tool_msg,
void *in_buf, u32 in_len, void *out_buf, u32 *out_len)
{
int ret = 0;
int index;
int msg_num = ARRAY_LEN(g_deal_msg_handle);
for (index = 0; index < msg_num; index++) {
if (tool_msg->module != g_deal_msg_handle[index].msg_name)
continue;
ret = g_deal_msg_handle[index].func(hal_dev, tool_msg,
in_buf, in_len, out_buf, out_len);
break;
}
if (index == msg_num)
ret = sss_tool_msg_to_nic(hal_dev, tool_msg,
in_buf, in_len, out_buf, out_len);
return ret;
}
static struct sss_hal_dev *sss_tool_get_hal_dev_by_msg(struct sss_tool_msg *tool_msg)
{
struct sss_hal_dev *hal_dev = NULL;
if (tool_msg->module >= SSS_TOOL_MSG_TO_SRV_DRV_BASE &&
tool_msg->module < SSS_TOOL_MSG_TO_DRIVER_MAX &&
tool_msg->msg_formate != SSS_TOOL_GET_DRV_VERSION) {
hal_dev = sss_get_lld_dev_by_dev_name(tool_msg->device_name,
tool_msg->module -
SSS_TOOL_MSG_TO_SRV_DRV_BASE);
} else {
hal_dev = sss_get_lld_dev_by_chip_name(tool_msg->device_name);
if (!hal_dev)
hal_dev = sss_get_lld_dev_by_dev_name(tool_msg->device_name,
SSS_SERVICE_TYPE_MAX);
}
if (tool_msg->module == SSS_TOOL_MSG_TO_NIC_DRIVER &&
(tool_msg->msg_formate == SSS_TOOL_GET_XSFP_INFO ||
tool_msg->msg_formate == SSS_TOOL_GET_XSFP_PRESENT))
hal_dev = sss_get_lld_dev_by_chip_and_port(tool_msg->device_name,
tool_msg->port_id);
return hal_dev;
}
static int sss_tool_check_msg_valid(struct sss_tool_msg *tool_msg)
{
if (tool_msg->buf_out_size > SSS_TOOL_BUF_SIZE_MAX ||
tool_msg->buf_in_size > SSS_TOOL_BUF_SIZE_MAX) {
tool_err("Invalid in buf len: %u or out buf len: %u\n",
tool_msg->buf_in_size, tool_msg->buf_out_size);
return -EFAULT;
}
return 0;
}
static long sss_tool_msg_ioctl(unsigned long arg)
{
int ret = 0;
u32 in_len = 0;
u32 expect_out_len = 0;
u32 out_len = 0;
void *in_buf = NULL;
void *out_buf = NULL;
struct sss_hal_dev *hal_dev = NULL;
struct sss_tool_msg tool_msg = {0};
if (copy_from_user(&tool_msg, (void *)arg, sizeof(tool_msg))) {
tool_err("Fail to copy msg from user space\n");
return -EFAULT;
}
if (sss_tool_check_msg_valid(&tool_msg)) {
tool_err("Fail to check msg valid\n");
return -EFAULT;
}
tool_msg.device_name[IFNAMSIZ - 1] = '\0';
expect_out_len = tool_msg.buf_out_size;
in_len = tool_msg.buf_in_size;
hal_dev = sss_tool_get_hal_dev_by_msg(&tool_msg);
if (!hal_dev) {
if (tool_msg.msg_formate != SSS_TOOL_DEV_NAME_TEST)
tool_err("Fail to find device %s for module %d\n",
tool_msg.device_name, tool_msg.module);
return -ENODEV;
}
if (tool_msg.msg_formate == SSS_TOOL_DEV_NAME_TEST)
return 0;
ret = sss_tool_alloc_buf(hal_dev->hwdev, &tool_msg,
in_len, &in_buf, expect_out_len, &out_buf);
if (ret) {
tool_err("Fail to alloc cmd buf\n");
goto out_free_lock;
}
out_len = expect_out_len;
ret = sss_tool_deal_cmd(hal_dev, &tool_msg, in_buf, in_len, out_buf, &out_len);
if (ret) {
tool_err("Fail to execute cmd, module: %u, ret: %d.\n", tool_msg.module, ret);
goto out_free_buf;
}
if (out_len > expect_out_len) {
ret = -EFAULT;
tool_err("Fail to execute cmd, expected out len from user: %u, out len: %u\n",
expect_out_len, out_len);
goto out_free_buf;
}
ret = sss_tool_copy_to_user(&tool_msg, out_len, out_buf);
if (ret)
tool_err("Fail to copy return information to user space\n");
out_free_buf:
sss_tool_free_buf(hal_dev->hwdev, &tool_msg, in_buf, out_buf);
out_free_lock:
lld_dev_put(hal_dev);
return (long)ret;
}
static long sss_tool_knl_ffm_info_rd(struct sss_tool_dbg_param *dbg_param,
struct sss_tool_knl_dbg_info *dbg_info)
{
if (copy_to_user(dbg_param->param.ffm_rd, dbg_info->ffm,
(unsigned int)sizeof(*dbg_param->param.ffm_rd))) {
tool_err("Fail to copy ffm_info to user space\n");
return -EFAULT;
}
return 0;
}
static struct sss_card_node *sss_tool_find_card_node(char *chip_name)
{
int i;
struct sss_card_node *card_node = NULL;
for (i = 0; i < SSS_TOOL_CARD_MAX; i++) {
card_node = (struct sss_card_node *)g_card_node_array[i];
if (!card_node)
continue;
if (!strncmp(chip_name, card_node->chip_name, IFNAMSIZ))
break;
}
if (i == SSS_TOOL_CARD_MAX || !card_node)
return NULL;
g_card_id = i;
return card_node;
}
static long sss_tool_dbg_ioctl(unsigned int cmd_type, unsigned long arg)
{
struct sss_tool_knl_dbg_info *dbg_info = NULL;
struct sss_card_node *card_node = NULL;
struct sss_tool_dbg_param param = {0};
long ret;
if (copy_from_user(&param, (void *)arg, sizeof(param))) {
tool_err("Fail to copy msg param from user\n");
return -EFAULT;
}
sss_hold_chip_node();
card_node = sss_tool_find_card_node(param.chip_name);
if (!card_node) {
sss_put_chip_node();
tool_err("Fail to find card node %s\n", param.chip_name);
return -EFAULT;
}
dbg_info = (struct sss_tool_knl_dbg_info *)card_node->dbgtool_info;
down(&dbg_info->dbgtool_sem);
if (cmd_type == SSS_TOOL_DBG_CMD_FFM_RD) {
ret = sss_tool_knl_ffm_info_rd(&param, dbg_info);
} else if (cmd_type == SSS_TOOL_DBG_CMD_MSG_2_UP) {
tool_info("cmd(0x%x) not suppose.\n", cmd_type);
ret = 0;
} else {
tool_err("Fail to execute cmd(0x%x) ,it is not support\n", cmd_type);
ret = -EFAULT;
}
up(&dbg_info->dbgtool_sem);
sss_put_chip_node();
return ret;
}
static int sss_tool_release(struct inode *pnode, struct file *pfile)
{
return 0;
}
static int sss_tool_open(struct inode *pnode, struct file *pfile)
{
return 0;
}
static ssize_t sss_tool_read(struct file *pfile, char __user *ubuf,
size_t size, loff_t *ppos)
{
return 0;
}
static ssize_t sss_tool_write(struct file *pfile, const char __user *ubuf,
size_t size, loff_t *ppos)
{
return 0;
}
static long sss_tool_unlocked_ioctl(struct file *pfile,
unsigned int cmd, unsigned long arg)
{
unsigned int cmd_type = _IOC_NR(cmd);
if (cmd_type == SSS_TOOL_CMD_TYPE)
return sss_tool_msg_ioctl(arg);
return sss_tool_dbg_ioctl(cmd_type, arg);
}
static int sss_tool_mem_mmap(struct file *filp, struct vm_area_struct *mem_area)
{
unsigned long mem_size = mem_area->vm_end - mem_area->vm_start;
phys_addr_t offset = (phys_addr_t)mem_area->vm_pgoff << PAGE_SHIFT;
phys_addr_t phy_addr;
if (mem_size > SSS_TOOL_MEM_MAP_SIZE) {
tool_err("Fail to map mem, mem_size :%ld, alloc size: %ld\n",
mem_size, SSS_TOOL_MEM_MAP_SIZE);
return -EAGAIN;
}
phy_addr = offset ? offset : g_card_pa[g_card_id];
if (!phy_addr) {
tool_err("Fail to map mem, card_id = %d phy_addr is 0\n", g_card_id);
return -EAGAIN;
}
mem_area->vm_page_prot = pgprot_noncached(mem_area->vm_page_prot);
if (remap_pfn_range(mem_area, mem_area->vm_start, (phy_addr >> PAGE_SHIFT),
mem_size, mem_area->vm_page_prot)) {
tool_err("Fail to remap pfn range.\n");
return -EAGAIN;
}
return 0;
}
static const struct file_operations sss_tool_file_ops = {
.owner = THIS_MODULE,
.release = sss_tool_release,
.open = sss_tool_open,
.read = sss_tool_read,
.write = sss_tool_write,
.unlocked_ioctl = sss_tool_unlocked_ioctl,
.mmap = sss_tool_mem_mmap,
};
static struct sss_tool_knl_dbg_info *sss_tool_alloc_dbg_info(void *hwdev)
{
struct sss_tool_knl_dbg_info *dbg_info = NULL;
dbg_info = (struct sss_tool_knl_dbg_info *)
kzalloc(sizeof(struct sss_tool_knl_dbg_info), GFP_KERNEL);
if (!dbg_info)
return NULL;
dbg_info->ffm = (struct sss_tool_ffm_record_info *)
kzalloc(sizeof(*dbg_info->ffm), GFP_KERNEL);
if (!dbg_info->ffm) {
tool_err("Fail to alloc ffm_record_info\n");
kfree(dbg_info);
return NULL;
}
return dbg_info;
}
static void sss_tool_free_dbg_info(struct sss_tool_knl_dbg_info *dbg_info)
{
kfree(dbg_info->ffm);
kfree(dbg_info);
}
static int sss_tool_get_node_id(struct sss_card_node *card_node, int *node_id)
{
int ret;
ret = sscanf(card_node->chip_name, SSS_CHIP_NAME "%d", node_id);
if (ret < 0) {
tool_err("Fail to get card id\n");
return -ENOMEM;
}
return 0;
}
static int sss_tool_add_func_to_card_node(void *hwdev, struct sss_card_node *card_node)
{
int func_id = sss_get_func_id(hwdev);
struct sss_tool_knl_dbg_info *dbg_info = NULL;
int ret;
int node_id;
if (sss_get_func_type(hwdev) != SSS_FUNC_TYPE_VF)
card_node->func_handle_array[func_id] = hwdev;
if (card_node->func_num++)
return 0;
dbg_info = sss_tool_alloc_dbg_info(hwdev);
if (!dbg_info) {
ret = -ENOMEM;
tool_err("Fail to alloc dbg_info\n");
goto alloc_dbg_info_err;
}
card_node->dbgtool_info = dbg_info;
sema_init(&dbg_info->dbgtool_sem, 1);
ret = sss_tool_get_node_id(card_node, &node_id);
if (ret) {
tool_err("Fail to add node to global array\n");
goto get_node_id_err;
}
g_card_node_array[node_id] = card_node;
return 0;
get_node_id_err:
sss_tool_free_dbg_info(dbg_info);
card_node->dbgtool_info = NULL;
alloc_dbg_info_err:
card_node->func_num--;
if (sss_get_func_type(hwdev) != SSS_FUNC_TYPE_VF)
card_node->func_handle_array[func_id] = NULL;
return ret;
}
static void sss_tool_del_func_in_card_node(void *hwdev, struct sss_card_node *card_node)
{
struct sss_tool_knl_dbg_info *dbg_info = card_node->dbgtool_info;
int func_id = sss_get_func_id(hwdev);
int node_id;
if (sss_get_func_type(hwdev) != SSS_FUNC_TYPE_VF)
card_node->func_handle_array[func_id] = NULL;
if (--card_node->func_num)
return;
sss_tool_get_node_id(card_node, &node_id);
if (node_id < SSS_TOOL_CARD_MAX)
g_card_node_array[node_id] = NULL;
sss_tool_free_dbg_info(dbg_info);
card_node->dbgtool_info = NULL;
if (node_id < SSS_TOOL_CARD_MAX)
(void)sss_tool_free_card_mem(node_id);
}
static int sss_tool_create_dev(void)
{
int ret;
struct device *pdevice = NULL;
ret = alloc_chrdev_region(&g_dev_id, 0, 1, SSS_TOOL_DEV_NAME);
if (ret) {
tool_err("Fail to alloc sssnic_nictool_dev region(0x%x)\n", ret);
return ret;
}
g_nictool_class = class_create(THIS_MODULE, SSS_TOOL_DEV_CLASS);
if (IS_ERR(g_nictool_class)) {
tool_err("Fail to create sssnic_nictool_class\n");
ret = -EFAULT;
goto create_class_err;
}
cdev_init(&g_nictool_cdev, &sss_tool_file_ops);
ret = cdev_add(&g_nictool_cdev, g_dev_id, 1);
if (ret < 0) {
tool_err("Fail to add sssnic_nictool_dev to operating system (0x%x)\n", ret);
goto add_cdev_err;
}
pdevice = device_create(g_nictool_class, NULL, g_dev_id, NULL, SSS_TOOL_DEV_NAME);
if (IS_ERR(pdevice)) {
tool_err("Fail to create sssnic_nictool_dev on operating system\n");
ret = -EFAULT;
goto create_device_err;
}
tool_info("Success to register sssnic_nictool_dev to system\n");
return 0;
create_device_err:
cdev_del(&g_nictool_cdev);
add_cdev_err:
class_destroy(g_nictool_class);
create_class_err:
g_nictool_class = NULL;
unregister_chrdev_region(g_dev_id, 1);
return ret;
}
static void sss_tool_destroy_dev(void)
{
device_destroy(g_nictool_class, g_dev_id);
cdev_del(&g_nictool_cdev);
class_destroy(g_nictool_class);
g_nictool_class = NULL;
unregister_chrdev_region(g_dev_id, 1);
tool_info("Success to unregister sssnic_nictool_dev to system\n");
}
int sss_tool_init(void *hwdev, void *chip_node)
{
struct sss_card_node *card_node = (struct sss_card_node *)chip_node;
int ret;
ret = sss_tool_add_func_to_card_node(hwdev, card_node);
if (ret) {
tool_err("Fail to add func to card node\n");
return ret;
}
if (g_nictool_ref_cnt++) {
tool_info("sssnic_nictool_dev has already create\n");
return 0;
}
ret = sss_tool_create_dev();
if (ret) {
tool_err("Fail to create sssnic_nictool_dev\n");
goto out;
}
return 0;
out:
g_nictool_ref_cnt--;
sss_tool_del_func_in_card_node(hwdev, card_node);
return ret;
}
void sss_tool_uninit(void *hwdev, void *chip_node)
{
struct sss_card_node *chip_info = (struct sss_card_node *)chip_node;
sss_tool_del_func_in_card_node(hwdev, chip_info);
if (g_nictool_ref_cnt == 0)
return;
if (--g_nictool_ref_cnt)
return;
if (!g_nictool_class || IS_ERR(g_nictool_class)) {
tool_err("Fail to uninit sssnictool, tool class is NULL.\n");
return;
}
sss_tool_destroy_dev();
}
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2021 3snic Technologies Co., Ltd */
#define pr_fmt(fmt) KBUILD_MODNAME ": [TOOL]" fmt
#include <net/sock.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/time.h>
#include "sss_linux_kernel.h"
#include "sss_hw.h"
#include "sss_hwdev.h"
#include "sss_tool.h"
#include "sss_csr.h"
#include "sss_adapter_mgmt.h"
#include "sss_mgmt_info.h"
#include "sss_pci_global.h"
#include "sss_hwif_api.h"
typedef int (*sss_tool_hw_cmd_func)(struct sss_hal_dev *hal_dev, const void *buf_in,
u32 in_size, void *buf_out, u32 *out_size);
struct sss_tool_hw_cmd_handle {
enum sss_tool_driver_cmd_type cmd_type;
sss_tool_hw_cmd_func func;
};
int sss_tool_get_func_type(struct sss_hal_dev *hal_dev, const void *buf_in, u32 in_size,
void *buf_out, u32 *out_size)
{
if (*out_size != sizeof(u16) || !buf_out) {
tool_err("Invalid out_size from user :%u, expect: %lu\n", *out_size, sizeof(u16));
return -EFAULT;
}
*(u16 *)buf_out = (u16)sss_get_func_type(SSS_TO_HWDEV(hal_dev));
return 0;
}
int sss_tool_get_func_id(struct sss_hal_dev *hal_dev, const void *buf_in, u32 in_size,
void *buf_out, u32 *out_size)
{
if (*out_size != sizeof(u16) || !buf_out) {
tool_err("Invalid out_size from user :%u, expect: %lu\n", *out_size, sizeof(u16));
return -EFAULT;
}
*(u16 *)buf_out = (u16)sss_get_func_id(SSS_TO_HWDEV(hal_dev));
return 0;
}
int sss_tool_get_hw_driver_stats(struct sss_hal_dev *hal_dev, const void *buf_in, u32 in_size,
void *buf_out, u32 *out_size)
{
struct sss_hwdev *hwdev = hal_dev->hwdev;
struct sss_card_node *node = hwdev->chip_node;
struct sss_hw_stats *stats = buf_out;
struct sss_hw_stats *tmp = stats;
if (!hwdev)
return -EINVAL;
if (*out_size != sizeof(struct sss_hw_stats) || !stats) {
tool_err("Invalid out_size from user :%u, expect: %lu\n",
*out_size, sizeof(struct sss_hw_stats));
return -EFAULT;
}
memcpy(stats, &hwdev->hw_stats, sizeof(struct sss_hw_stats));
atomic_set(&tmp->nic_ucode_event_stats[SSS_CHN_BUSY],
atomic_read(&node->channel_timeout_cnt));
return 0;
}
static int sss_tool_clear_hw_driver_stats(struct sss_hal_dev *hal_dev, const void *buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
struct sss_hwdev *hwdev = hal_dev->hwdev;
struct sss_card_node *node = hwdev->chip_node;
memset((void *)&hwdev->hw_stats, 0, sizeof(struct sss_hw_stats));
memset((void *)hwdev->chip_fault_stats, 0, SSS_TOOL_CHIP_FAULT_SIZE);
if (SSS_SUPPORT_CHANNEL_DETECT(hwdev) && atomic_read(&node->channel_timeout_cnt)) {
atomic_set(&node->channel_timeout_cnt, 0);
hwdev->aeq_busy_cnt = 0;
#if !defined(__UEFI__) && !defined(VMWARE)
queue_delayed_work(hwdev->workq, &hwdev->channel_detect_task,
msecs_to_jiffies(SSSNIC_CHANNEL_DETECT_PERIOD));
#endif
}
if (*out_size != sizeof(struct sss_hw_stats)) {
tool_err("Invalid out_size from user :%u, expect: %lu\n",
*out_size, sizeof(struct sss_hw_stats));
return -EFAULT;
}
return 0;
}
static int sss_tool_get_self_test_result(struct sss_hal_dev *hal_dev,
const void *buf_in, u32 in_size,
void *buf_out, u32 *out_size)
{
u32 val;
if (*out_size != sizeof(u32) || !buf_out) {
tool_err("Invalid out_size from user :%u, expect: %lu\n",
*out_size, sizeof(u32));
return -EFAULT;
}
val = sss_chip_read_reg(SSS_TO_HWIF(hal_dev->hwdev), SSS_MGMT_HEALTH_STATUS_ADDR);
*(u32 *)buf_out = val;
return 0;
}
static void sss_tool_get_chip_fault_stats(const void *hwdev, u8 *chip_fault_stats, u32 offset)
{
u32 size;
if (offset >= SSS_TOOL_CHIP_FAULT_SIZE) {
tool_err("Invalid chip offset value: %d\n", offset);
return;
}
size = min(SSS_TOOL_DRV_BUF_SIZE_MAX, SSS_TOOL_CHIP_FAULT_SIZE - (int)offset);
memcpy(chip_fault_stats, ((struct sss_hwdev *)hwdev)->chip_fault_stats
+ offset, size);
}
static int sss_tool_get_chip_faults_stats(struct sss_hal_dev *hal_dev,
const void *buf_in, u32 in_size,
void *buf_out, u32 *out_size)
{
u32 offset = 0;
struct sss_tool_cmd_chip_fault_stats *info = NULL;
if (!buf_in || !buf_out || *out_size != sizeof(*info) ||
in_size != sizeof(*info)) {
tool_err("Invalid out_size from user: %d, expect: %lu\n", *out_size, sizeof(*info));
return -EFAULT;
}
info = (struct sss_tool_cmd_chip_fault_stats *)buf_in;
offset = info->offset;
info = (struct sss_tool_cmd_chip_fault_stats *)buf_out;
sss_tool_get_chip_fault_stats(hal_dev->hwdev,
info->chip_fault_stats, offset);
return 0;
}
static int sss_tool_get_single_card_info(struct sss_hal_dev *hal_dev, const void *buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
if (!buf_out || *out_size != sizeof(struct sss_tool_card_info)) {
tool_err("Invalid buf out is NULL, or out_size != %lu\n",
sizeof(struct sss_tool_card_info));
return -EINVAL;
}
sss_get_card_info(hal_dev->hwdev, buf_out);
return 0;
}
static int sss_tool_is_driver_in_vm(struct sss_hal_dev *hal_dev,
const void *buf_in, u32 in_size,
void *buf_out, u32 *out_size)
{
if (!buf_out || (*out_size != sizeof(u8))) {
tool_err("Invalid parameter, buf_out is NULL or out_size != %lu\n", sizeof(u8));
return -EINVAL;
}
*((u8 *)buf_out) = sss_is_in_host() ? 0 : 1;
return 0;
}
static int sss_tool_get_all_chip_id_cmd(struct sss_hal_dev *hal_dev,
const void *buf_in, u32 in_size,
void *buf_out, u32 *out_size)
{
if (*out_size != sizeof(struct sss_card_id) || !buf_out) {
tool_err("Invalid parameter: out_size %u, expect %lu\n",
*out_size, sizeof(struct sss_card_id));
return -EFAULT;
}
sss_get_all_chip_id(buf_out);
return 0;
}
static int sss_tool_get_card_id(char *dev_name, int *id)
{
int ret;
ret = sscanf(dev_name, SSS_CHIP_NAME "%d", id);
if (ret < 0) {
tool_err("Fail to get card id\n");
return ret;
}
if (*id >= SSS_TOOL_CARD_MAX || *id < 0) {
tool_err("Invalid chip id %d, out of range: [0-%d]\n", *id, SSS_TOOL_CARD_MAX - 1);
return -EINVAL;
}
return 0;
}
static void sss_tool_get_pf_dev_info_param(struct sss_tool_pf_dev_info *dev_info, int card_id,
void **func_array)
{
u32 func_id;
void *hwdev = NULL;
struct pci_dev *pdev = NULL;
for (func_id = 0; func_id < SSS_TOOL_PF_DEV_MAX; func_id++) {
hwdev = (void *)func_array[func_id];
dev_info[func_id].phy_addr = g_card_pa[card_id];
if (!hwdev) {
dev_info[func_id].bar0_size = 0;
dev_info[func_id].bus = 0;
dev_info[func_id].slot = 0;
dev_info[func_id].func = 0;
} else {
pdev = (struct pci_dev *)sss_get_pcidev_hdl(hwdev);
dev_info[func_id].bar0_size = pci_resource_len(pdev, 0);
dev_info[func_id].bus = pdev->bus->number;
dev_info[func_id].slot = PCI_SLOT(pdev->devfn);
dev_info[func_id].func = PCI_FUNC(pdev->devfn);
}
}
}
static int sss_tool_get_card_adm_mem(int card_id)
{
int i;
unsigned char *card_va = NULL;
g_card_id = card_id;
if (!g_card_va[card_id]) {
g_card_va[card_id] =
(void *)__get_free_pages(GFP_KERNEL, SSS_TOOL_PAGE_ORDER);
if (!g_card_va[card_id]) {
tool_err("Fail to alloc adm memory for card %d!\n", card_id);
return -EFAULT;
}
memset(g_card_va[card_id], 0, PAGE_SIZE * (1 << SSS_TOOL_PAGE_ORDER));
g_card_pa[card_id] = virt_to_phys(g_card_va[card_id]);
if (!g_card_pa[card_id]) {
tool_err("Invalid phy addr for card %d is 0\n", card_id);
free_pages((unsigned long)g_card_va[card_id], SSS_TOOL_PAGE_ORDER);
g_card_va[card_id] = NULL;
return -EFAULT;
}
card_va = g_card_va[card_id];
for (i = 0; i < (1 << SSS_TOOL_PAGE_ORDER); i++) {
SetPageReserved(virt_to_page(card_va));
card_va += PAGE_SIZE;
}
}
return 0;
}
static int sss_tool_get_pf_dev_info(struct sss_hal_dev *hal_dev, const void *buf_in, u32 in_size,
void *buf_out, u32 *out_size)
{
int id;
int ret;
struct sss_tool_pf_dev_info *info = buf_out;
struct sss_card_node *node = sss_get_card_node(hal_dev);
if (!buf_out || *out_size != sizeof(struct sss_tool_pf_dev_info) * SSS_TOOL_PF_DEV_MAX) {
tool_err("Invalid param: out_size %u, expect %lu\n",
*out_size, sizeof(info) * SSS_TOOL_PF_DEV_MAX);
return -EFAULT;
}
ret = sss_tool_get_card_id(node->chip_name, &id);
if (ret)
return ret;
sss_tool_get_pf_dev_info_param(info, id, node->func_handle_array);
ret = sss_tool_get_card_adm_mem(id);
if (ret) {
tool_err("Fail to get adm memory for userspace %s\n", node->chip_name);
return -EFAULT;
}
return 0;
}
long sss_tool_free_card_mem(int id)
{
unsigned char *va = NULL;
int i;
if (!g_card_va[id])
return 0;
va = g_card_va[id];
for (i = 0; i < (1 << SSS_TOOL_PAGE_ORDER); i++) {
ClearPageReserved(virt_to_page(va));
va += PAGE_SIZE;
}
free_pages((unsigned long)g_card_va[id], SSS_TOOL_PAGE_ORDER);
g_card_va[id] = NULL;
g_card_pa[id] = 0;
return 0;
}
static int sss_tool_free_all_card_mem(struct sss_hal_dev *hal_dev, const void *buf_in, u32 in_size,
void *buf_out, u32 *out_size)
{
int id;
int ret;
struct sss_card_node *node = sss_get_card_node(hal_dev);
ret = sss_tool_get_card_id(node->chip_name, &id);
if (ret)
return ret;
sss_tool_free_card_mem(id);
return 0;
}
static int sss_tool_check_card_info_param(char *dev_name, const void *buf_out, u32 out_size)
{
int ret;
if (!buf_out || out_size != sizeof(struct sss_card_func_info)) {
tool_err("Invalid out_size %u, expect %lu\n",
out_size, sizeof(struct sss_card_func_info));
return -EINVAL;
}
ret = memcmp(dev_name, SSS_CHIP_NAME, strlen(SSS_CHIP_NAME));
if (ret) {
tool_err("Invalid chip name %s\n", dev_name);
return ret;
}
return 0;
}
static int sss_tool_get_card_func_info(struct sss_hal_dev *hal_dev, const void *buf_in, u32 in_size,
void *buf_out, u32 *out_size)
{
int ret;
int id = 0;
struct sss_card_func_info *info = buf_out;
struct sss_card_node *node = sss_get_card_node(hal_dev);
ret = sss_tool_check_card_info_param(node->chip_name, buf_out, *out_size);
if (ret)
return ret;
ret = sss_tool_get_card_id(node->chip_name, &id);
if (ret)
return ret;
sss_get_card_func_info(node->chip_name, info);
if (!info->pf_num) {
tool_err("Fail to get card func info, chip name %s\n", node->chip_name);
return -EFAULT;
}
ret = sss_tool_get_card_adm_mem(id);
if (ret) {
tool_err("Fail to get adm memory for userspace %s\n", node->chip_name);
return -EFAULT;
}
info->usr_adm_pa = g_card_pa[id];
return 0;
}
static int sss_tool_get_pf_cap_info(struct sss_hal_dev *hal_dev, const void *buf_in, u32 in_size,
void *buf_out, u32 *out_size)
{
struct sss_hwdev *hwdev = NULL;
struct sss_card_node *node = sss_get_card_node(hal_dev);
struct sss_svc_cap_info *in_info = (struct sss_svc_cap_info *)buf_in;
struct sss_svc_cap_info *out_info = (struct sss_svc_cap_info *)buf_out;
if (*out_size != sizeof(struct sss_svc_cap_info) ||
in_size != sizeof(struct sss_svc_cap_info) ||
!buf_in || !buf_out) {
tool_err("Invalid out_size %u, in_size: %u, expect %lu\n",
*out_size, in_size, sizeof(struct sss_svc_cap_info));
return -EINVAL;
}
if (in_info->func_id >= SSS_MAX_FUNC) {
tool_err("Invalid func id: %u, max_num: %u\n",
in_info->func_id, SSS_MAX_FUNC);
return -EINVAL;
}
sss_hold_chip_node();
hwdev = (struct sss_hwdev *)(node->func_handle_array)[in_info->func_id];
if (!hwdev) {
sss_put_chip_node();
return -EINVAL;
}
memcpy(&out_info->cap, SSS_TO_SVC_CAP(hwdev), sizeof(struct sss_service_cap));
sss_put_chip_node();
return 0;
}
static int sss_tool_get_hw_drv_version(struct sss_hal_dev *hal_dev, const void *buf_in, u32 in_size,
void *buf_out, u32 *out_size)
{
int ret;
struct sss_tool_drv_version_info *info = buf_out;
if (!buf_out || *out_size != sizeof(*info)) {
tool_err("Invalid param, buf_out is NULL or out_size:%u, expect: %lu\n",
*out_size, sizeof(*info));
return -EINVAL;
}
ret = snprintf(info->ver, sizeof(info->ver), "%s %s", SSS_DRV_VERSION,
__TIME_STR__);
if (ret < 0)
return -EINVAL;
return 0;
}
static int sss_tool_get_pf_id(struct sss_hal_dev *hal_dev, const void *buf_in, u32 in_size,
void *buf_out, u32 *out_size)
{
struct sss_tool_pf_info *info = NULL;
struct sss_card_node *node = sss_get_card_node(hal_dev);
u32 port_id;
int ret;
if (!node)
return -ENODEV;
if (!buf_out || (*out_size != sizeof(*info)) || !buf_in || in_size != sizeof(port_id)) {
tool_err("Invalid out_size from user: %u, expect: %lu, in_size:%u\n",
*out_size, sizeof(*info), in_size);
return -EINVAL;
}
port_id = *((u32 *)buf_in);
info = (struct sss_tool_pf_info *)buf_out;
ret = sss_get_pf_id(node, port_id, &info->pf_id, &info->valid);
if (ret != 0)
return ret;
*out_size = sizeof(*info);
return 0;
}
struct sss_tool_hw_cmd_handle g_hw_cmd_handle[] = {
{SSS_TOOL_FUNC_TYPE, sss_tool_get_func_type},
{SSS_TOOL_GET_FUNC_IDX, sss_tool_get_func_id},
{SSS_TOOL_GET_CHIP_INFO, sss_tool_get_card_func_info},
{SSS_TOOL_GET_DRV_VERSION, sss_tool_get_hw_drv_version},
{SSS_TOOL_GET_PF_ID, sss_tool_get_pf_id},
{SSS_TOOL_GET_FUNC_CAP, sss_tool_get_pf_cap_info},
{SSS_TOOL_GET_SELF_TEST_RES, sss_tool_get_self_test_result},
{SSS_TOOL_GET_CHIP_ID, sss_tool_get_all_chip_id_cmd},
{SSS_TOOL_GET_PF_DEV_INFO, sss_tool_get_pf_dev_info},
{SSS_TOOL_IS_DRV_IN_VM, sss_tool_is_driver_in_vm},
{SSS_TOOL_CMD_FREE_MEM, sss_tool_free_all_card_mem},
{SSS_TOOL_GET_CHIP_FAULT_STATS, (sss_tool_hw_cmd_func)sss_tool_get_chip_faults_stats},
{SSS_TOOL_GET_SINGLE_CARD_INFO, (sss_tool_hw_cmd_func)sss_tool_get_single_card_info},
{SSS_TOOL_GET_HW_STATS, (sss_tool_hw_cmd_func)sss_tool_get_hw_driver_stats},
{SSS_TOOL_CLEAR_HW_STATS, sss_tool_clear_hw_driver_stats},
};
int sss_tool_msg_to_hw(struct sss_hal_dev *hal_dev, struct sss_tool_msg *tool_msg,
void *buf_in, u32 in_size, void *buf_out, u32 *out_size)
{
int id;
int ret = 0;
int cmd_num = ARRAY_LEN(g_hw_cmd_handle);
enum sss_tool_driver_cmd_type cmd =
(enum sss_tool_driver_cmd_type)(tool_msg->msg_formate);
for (id = 0; id < cmd_num; id++) {
if (cmd == g_hw_cmd_handle[id].cmd_type) {
ret = g_hw_cmd_handle[id].func
(hal_dev, buf_in, in_size, buf_out, out_size);
break;
}
}
if (id == cmd_num) {
tool_err("Fail to send msg to hw, cmd: %d out of range\n", cmd);
return -EINVAL;
}
return ret;
}
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2021 3snic Technologies Co., Ltd */
#ifndef SSS_TOOL_SDK_H
#define SSS_TOOL_SDK_H
#include "sss_tool_comm.h"
#include "sss_tool_hw.h"
#include "sss_hw.h"
long sss_tool_free_card_mem(int id);
int sss_tool_msg_to_hw(struct sss_hal_dev *hal_dev, struct sss_tool_msg *tool_msg,
void *buf_in, u32 in_size, void *buf_out, u32 *out_size);
#endif
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2021 3snic Technologies Co., Ltd */
#define pr_fmt(fmt) KBUILD_MODNAME ": [TOOL]" fmt
#include "sss_hwdev.h"
#include "sss_hwif_adm.h"
#include "sss_tool_comm.h"
#include "sss_tool_sm.h"
#define SSS_TOOL_CHIP_ACK 1
#define SSS_TOOL_CHIP_NOACK 0
#define SSS_TOOL_SM_CHIP_OP_READ 0x2
#define SSS_TOOL_SM_CHIP_OP_READ_CLEAR 0x6
#define SSS_TOOL_BIT_32 32
struct sss_tool_sm_in {
int node;
int id;
int instance;
};
struct sss_tool_sm_out {
u64 val1;
u64 val2;
};
union sss_tool_sm_chip_request_head {
struct {
u32 pad:15;
u32 ack:1;
u32 op_id:5;
u32 instance:6;
u32 src:5;
} bs;
u32 value;
};
/* counter read request struct */
struct sss_tool_sm_chip_request {
u32 extra;
union sss_tool_sm_chip_request_head head;
u32 ctr_id;
u32 initial;
u32 pad;
};
/* counter read response union */
union sss_tool_chip_rd_response {
struct {
u32 value1:16;
u32 pad0:16;
u32 pad1[3];
} bs_ss16_rsp;
struct {
u32 value1;
u32 pad[3];
} bs_ss32_rsp;
struct {
u32 value1:20;
u32 pad0:12;
u32 value2:12;
u32 pad1:20;
u32 pad2[2];
} bs_sp_rsp;
struct {
u32 value1;
u32 value2;
u32 pad[2];
} bs_bs64_rsp;
struct {
u32 val1_h;
u32 val1_l;
u32 val2_h;
u32 val2_l;
} bs_bp64_rsp;
};
typedef int (*sss_tool_sm_handler_func)(void *hwdev, u32 id, u8 instance,
u8 node, struct sss_tool_sm_out *out_buf);
struct sss_tool_sm_handler {
enum sss_tool_sm_cmd_type msg_name;
sss_tool_sm_handler_func sm_func;
};
static void sss_tool_sm_read_msg_create(struct sss_tool_sm_chip_request *request,
u8 instance_id, u8 op_id,
u8 ack, u32 ctr_id, u32 init_val)
{
request->head.value = 0;
request->head.bs.op_id = op_id;
request->head.bs.ack = ack;
request->head.bs.instance = instance_id;
request->head.value = HTONL(request->head.value);
request->initial = init_val;
request->ctr_id = ctr_id;
request->ctr_id = HTONL(request->ctr_id);
}
static void sss_tool_sm_node_htonl(u32 *node, u32 len)
{
u32 *new_node = node;
u32 i;
for (i = 0; i < len; i++) {
*new_node = HTONL(*new_node);
new_node++;
}
}
static int sss_tool_sm_adm_msg_rd(void *hwdev, u32 id, u8 instance,
u8 node, union sss_tool_chip_rd_response *rsp, u8 opcode)
{
struct sss_tool_sm_chip_request req = {0};
int ret;
if (!hwdev)
return -EFAULT;
if (!SSS_SUPPORT_ADM_MSG((struct sss_hwdev *)hwdev)) {
tool_err("Fail to read sm data, device not support adm msg\n");
return -EPERM;
}
sss_tool_sm_read_msg_create(&req, instance, opcode,
SSS_TOOL_CHIP_ACK, id, 0);
ret = sss_adm_msg_read_ack(hwdev, node, (u8 *)&req,
(unsigned short)sizeof(req),
(void *)rsp,
(unsigned short)sizeof(*rsp));
if (ret) {
tool_err("Fail to read sm data from adm msg, err(%d)\n", ret);
return ret;
}
sss_tool_sm_node_htonl((u32 *)rsp, sizeof(*rsp) / sizeof(u32));
return 0;
}
static int sss_tool_sm_msg_rd16(void *hwdev, u32 id, u8 instance,
u8 node, struct sss_tool_sm_out *out_buf)
{
u16 val1;
union sss_tool_chip_rd_response rsp;
int ret = 0;
ret = sss_tool_sm_adm_msg_rd(hwdev, id, instance, node, &rsp, SSS_TOOL_SM_CHIP_OP_READ);
if (ret) {
tool_err("Fail to read sm 32 bits\n");
val1 = ~0;
goto out;
}
val1 = rsp.bs_ss16_rsp.value1;
out:
out_buf->val1 = val1;
return ret;
}
static int sss_tool_sm_msg_rd32(void *hwdev, u32 id, u8 instance,
u8 node, struct sss_tool_sm_out *out_buf)
{
u32 val1;
union sss_tool_chip_rd_response rsp;
int ret = 0;
ret = sss_tool_sm_adm_msg_rd(hwdev, id, instance, node, &rsp, SSS_TOOL_SM_CHIP_OP_READ);
if (ret) {
tool_err("Fail to read sm 32 bits\n");
val1 = ~0;
goto out;
}
val1 = rsp.bs_ss32_rsp.value1;
out:
out_buf->val1 = val1;
return ret;
}
static int sss_tool_sm_msg_rd32_clear(void *hwdev, u32 id, u8 instance,
u8 node, struct sss_tool_sm_out *out_buf)
{
u32 val1;
union sss_tool_chip_rd_response rsp;
int ret = 0;
ret = sss_tool_sm_adm_msg_rd(hwdev, id, instance, node,
&rsp, SSS_TOOL_SM_CHIP_OP_READ_CLEAR);
if (ret) {
tool_err("Fail to read sm 32 bits\n");
val1 = ~0;
goto out;
}
val1 = rsp.bs_ss32_rsp.value1;
out:
out_buf->val1 = val1;
return ret;
}
static int sss_tool_sm_msg_rd128(void *hwdev, u32 id, u8 instance,
u8 node, struct sss_tool_sm_out *out_buf)
{
u64 val1 = 0;
u64 val2 = 0;
int ret = 0;
union sss_tool_chip_rd_response rsp;
if ((id & 0x1) != 0) {
tool_err("Invalid id(%u), It is odd number\n", id);
val1 = ~0;
val2 = ~0;
ret = -EINVAL;
goto out;
}
ret = sss_tool_sm_adm_msg_rd(hwdev, id, instance, node,
&rsp, SSS_TOOL_SM_CHIP_OP_READ);
if (ret) {
tool_err("Fail to read sm 128 bits\n");
val1 = ~0;
val2 = ~0;
goto out;
}
sss_tool_sm_node_htonl((u32 *)&rsp, sizeof(rsp) / sizeof(u32));
val1 = ((u64)rsp.bs_bp64_rsp.val1_h << SSS_TOOL_BIT_32) | rsp.bs_bp64_rsp.val1_l;
val2 = ((u64)rsp.bs_bp64_rsp.val2_h << SSS_TOOL_BIT_32) | rsp.bs_bp64_rsp.val2_l;
out:
out_buf->val1 = val1;
out_buf->val2 = val2;
return ret;
}
static int sss_tool_sm_msg_rd128_clear(void *hwdev, u32 id, u8 instance,
u8 node, struct sss_tool_sm_out *out_buf)
{
u64 val1 = 0;
u64 val2 = 0;
int ret = 0;
union sss_tool_chip_rd_response rsp;
if ((id & 0x1) != 0) {
tool_err("Invalid id(%u), It is odd number\n", id);
val1 = ~0;
val2 = ~0;
ret = -EINVAL;
goto out;
}
ret = sss_tool_sm_adm_msg_rd(hwdev, id, instance, node,
&rsp, SSS_TOOL_SM_CHIP_OP_READ_CLEAR);
if (ret) {
tool_err("Fail to read sm 128 bits\n");
val1 = ~0;
val2 = ~0;
goto out;
}
val1 = ((u64)rsp.bs_bp64_rsp.val1_h << SSS_TOOL_BIT_32) | rsp.bs_bp64_rsp.val1_l;
val2 = ((u64)rsp.bs_bp64_rsp.val2_h << SSS_TOOL_BIT_32) | rsp.bs_bp64_rsp.val2_l;
out:
out_buf->val1 = val1;
out_buf->val2 = val2;
return ret;
}
static int sss_tool_sm_msg_rd64(void *hwdev, u32 id, u8 instance,
u8 node, struct sss_tool_sm_out *out_buf)
{
u64 val1 = 0;
int ret = 0;
union sss_tool_chip_rd_response rsp;
ret = sss_tool_sm_adm_msg_rd(hwdev, id, instance, node,
&rsp, SSS_TOOL_SM_CHIP_OP_READ);
if (ret) {
tool_err("Fail to read sm 64 bits\n");
val1 = ~0;
goto out;
}
val1 = ((u64)rsp.bs_bs64_rsp.value1 << SSS_TOOL_BIT_32) | rsp.bs_bs64_rsp.value2;
out:
out_buf->val1 = val1;
return ret;
}
static int sss_tool_sm_msg_rd64_clear(void *hwdev, u32 id, u8 instance,
u8 node, struct sss_tool_sm_out *out_buf)
{
u64 val1 = 0;
int ret = 0;
union sss_tool_chip_rd_response rsp;
ret = sss_tool_sm_adm_msg_rd(hwdev, id, instance, node,
&rsp, SSS_TOOL_SM_CHIP_OP_READ_CLEAR);
if (ret) {
tool_err("Fail to read sm 64 bits\n");
val1 = ~0;
goto out;
}
val1 = ((u64)rsp.bs_bs64_rsp.value1 << SSS_TOOL_BIT_32) | rsp.bs_bs64_rsp.value2;
out:
out_buf->val1 = val1;
return ret;
}
const struct sss_tool_sm_handler g_sm_cmd_handle[] = {
{SSS_TOOL_SM_CMD_RD16, sss_tool_sm_msg_rd16},
{SSS_TOOL_SM_CMD_RD32, sss_tool_sm_msg_rd32},
{SSS_TOOL_SM_CMD_RD32_CLEAR, sss_tool_sm_msg_rd32_clear},
{SSS_TOOL_SM_CMD_RD64, sss_tool_sm_msg_rd64},
{SSS_TOOL_SM_CMD_RD64_CLEAR, sss_tool_sm_msg_rd64_clear},
{SSS_TOOL_SM_CMD_RD64_PAIR, sss_tool_sm_msg_rd128},
{SSS_TOOL_SM_CMD_RD64_PAIR_CLEAR, sss_tool_sm_msg_rd128_clear}
};
int sss_tool_msg_to_sm(struct sss_hal_dev *hal_dev, struct sss_tool_msg *msg,
void *in_buf, u32 in_len, void *out_buf, u32 *out_len)
{
int index;
int ret = 0;
int cmd_num = ARRAY_LEN(g_sm_cmd_handle);
u32 msg_formate = msg->msg_formate;
struct sss_tool_sm_in *sm_in = in_buf;
struct sss_tool_sm_out *sm_out = out_buf;
if (!in_buf || !out_buf || !out_len) {
tool_err("Invalid in_buf or out buf param\n");
return -EINVAL;
}
if (in_len != sizeof(*sm_in) || *out_len != sizeof(*sm_out)) {
tool_err("Invalid out buf size :%u, in buf size: %u\n",
*out_len, in_len);
return -EINVAL;
}
for (index = 0; index < cmd_num; index++) {
if (msg_formate != g_sm_cmd_handle[index].msg_name)
continue;
ret = g_sm_cmd_handle[index].sm_func(hal_dev->hwdev, (u32)sm_in->id,
(u8)sm_in->instance, (u8)sm_in->node, sm_out);
break;
}
if (index == cmd_num) {
tool_err("Fail to execute msg %d,could not find callback\n", msg_formate);
return -EINVAL;
}
if (ret != 0)
tool_err("Fail to get sm information, id:%u, instance:%u, node:%u, msg:%d\n",
sm_in->id, sm_in->instance, sm_in->node, msg_formate);
*out_len = sizeof(*sm_out);
return ret;
}
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2021 3snic Technologies Co., Ltd */
#ifndef SSS_TOOL_SM_H
#define SSS_TOOL_SM_H
#include "sss_pci_global.h"
#include "sss_tool_comm.h"
#include "sss_tool_hw.h"
#ifndef HTONL
#define HTONL(x) \
((((x) & 0x000000ff) << 24) | \
(((x) & 0x0000ff00) << 8) | \
(((x) & 0x00ff0000) >> 8) | \
(((x) & 0xff000000) >> 24))
#endif
int sss_tool_msg_to_sm(struct sss_hal_dev *hal_dev, struct sss_tool_msg *msg,
void *in_buf, u32 in_len, void *out_buf, u32 *out_len);
#endif
......@@ -85,6 +85,8 @@ bool sss_get_nic_capability(void *hwdev, struct sss_nic_service_cap *capability)
*/
bool sss_support_nic(void *hwdev);
bool sss_support_ppa(void *hwdev, struct sss_ppa_service_cap *cap);
/* *
* @brief sss_get_max_sq_num - get max queue number
* @param hwdev: device pointer to hwdev
......@@ -163,6 +165,8 @@ int sss_get_dev_present_flag(const void *hwdev);
*/
u8 sss_get_max_pf_num(void *hwdev);
u16 sss_nic_intr_num(void *hwdev);
/* *
* @brief sss_get_chip_present_state - get card present state
* @param hwdev: device pointer to hwdev
......
......@@ -171,7 +171,7 @@ enum sss_mod_type {
SSS_MOD_TYPE_FLR = 5,
SSS_MOD_TYPE_RSVD1 = 6,
SSS_MOD_TYPE_CFGM = 7, /* Configuration module */
SSS_MOD_TYPE_CQM = 8,
SSS_MOD_TYPE_QMM = 8,
SSS_MOD_TYPE_RSVD2 = 9,
COMM_MOD_FC = 10,
SSS_MOD_TYPE_OVS = 11,
......
......@@ -10,20 +10,26 @@
#include "sss_hw_event.h"
#include "sss_hw_aeq.h"
struct sss_qmm_stats {
atomic_t qmm_rsv_cnt[134];
};
struct sss_link_event_stats {
atomic_t link_down_stats;
atomic_t link_up_stats;
};
struct sss_fault_event_stats {
atomic_t chip_fault_stats[22][SSS_FAULT_LEVEL_MAX];
atomic_t fault_type_stat[SSS_FAULT_TYPE_MAX];
atomic_t pcie_fault_stats;
};
struct sss_hw_stats {
atomic_t heart_lost_stats;
struct sss_link_event_stats sss_link_event_stats;
struct sss_fault_event_stats sss_fault_event_stats;
struct sss_qmm_stats qmm_stats;
struct sss_link_event_stats link_event_stats;
struct sss_fault_event_stats fault_event_stats;
atomic_t nic_ucode_event_stats[SSS_ERR_MAX];
};
......
......@@ -23,7 +23,7 @@ enum sss_service_type {
SSS_SERVICE_TYPE_MAX,
SSS_SERVICE_TYPE_INTF = (1 << 15),
SSS_SERVICE_TYPE_CQM = (1 << 16),
SSS_SERVICE_TYPE_QMM = (1 << 16),
};
/* RDMA service capability */
......
......@@ -71,6 +71,8 @@ u8 sss_get_pcie_itf_id(void *hwdev);
*/
enum sss_func_type sss_get_func_type(void *hwdev);
enum sss_func_type sss_get_func_id(void *hwdev);
/* *
* @brief sss_get_glb_pf_vf_offset - get vf offset id of pf
* @param hwdev: device pointer to hwdev
......
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2021 3snic Technologies Co., Ltd */
#ifndef SSS_TOOL_COMM_H
#define SSS_TOOL_COMM_H
#define tool_err(format, ...) pr_err(format, ##__VA_ARGS__)
#define tool_warn(format, ...) pr_warn(format, ##__VA_ARGS__)
#define tool_info(format, ...) pr_info(format, ##__VA_ARGS__)
#define SSS_TOOL_SHOW_ITEM_LEN 32
#define SSS_TOOL_VERSION_INFO_LEN 128
#define SSS_TOOL_EPERM 1 /* Operation not permitted */
#define SSS_TOOL_EIO 2 /* I/O error */
#define SSS_TOOL_EINVAL 3 /* Invalid argument */
#define SSS_TOOL_EBUSY 4 /* Device or resource busy */
#define SSS_TOOL_EOPNOTSUPP 0xFF /* Operation not supported */
enum sss_tool_driver_cmd_type {
SSS_TOOL_GET_TX_INFO = 1,
SSS_TOOL_GET_Q_NUM,
SSS_TOOL_GET_TX_WQE_INFO,
SSS_TOOL_TX_MAPPING,
SSS_TOOL_GET_RX_INFO,
SSS_TOOL_GET_RX_WQE_INFO,
SSS_TOOL_GET_RX_CQE_INFO,
SSS_TOOL_UPRINT_FUNC_EN,
SSS_TOOL_UPRINT_FUNC_RESET,
SSS_TOOL_UPRINT_SET_PATH,
SSS_TOOL_UPRINT_GET_STATISTICS,
SSS_TOOL_FUNC_TYPE,
SSS_TOOL_GET_FUNC_IDX,
SSS_TOOL_GET_INTER_NUM,
SSS_TOOL_CLOSE_TX_STREAM,
SSS_TOOL_GET_DRV_VERSION,
SSS_TOOL_CLEAR_FUNC_STATS,
SSS_TOOL_GET_HW_STATS,
SSS_TOOL_CLEAR_HW_STATS,
SSS_TOOL_GET_SELF_TEST_RES,
SSS_TOOL_GET_CHIP_FAULT_STATS,
SSS_TOOL_NIC_RSVD1,
SSS_TOOL_NIC_RSVD2,
SSS_TOOL_NIC_RSVD3,
SSS_TOOL_GET_CHIP_ID,
SSS_TOOL_GET_SINGLE_CARD_INFO,
SSS_TOOL_GET_FIRMWARE_ACTIVE_STATUS,
SSS_TOOL_ROCE_DFX_FUNC,
SSS_TOOL_GET_DEVICE_ID,
SSS_TOOL_GET_PF_DEV_INFO,
SSS_TOOL_CMD_FREE_MEM,
SSS_TOOL_GET_LOOPBACK_MODE = 32,
SSS_TOOL_SET_LOOPBACK_MODE,
SSS_TOOL_SET_LINK_MODE,
SSS_TOOL_SET_PF_BW_LIMIT,
SSS_TOOL_GET_PF_BW_LIMIT,
SSS_TOOL_ROCE_CMD,
SSS_TOOL_GET_POLL_WEIGHT,
SSS_TOOL_SET_POLL_WEIGHT,
SSS_TOOL_GET_HOMOLOGUE,
SSS_TOOL_SET_HOMOLOGUE,
SSS_TOOL_GET_SSET_COUNT,
SSS_TOOL_GET_SSET_ITEMS,
SSS_TOOL_IS_DRV_IN_VM,
SSS_TOOL_LRO_ADPT_MGMT,
SSS_TOOL_SET_INTER_COAL_PARAM,
SSS_TOOL_GET_INTER_COAL_PARAM,
SSS_TOOL_GET_CHIP_INFO,
SSS_TOOL_GET_NIC_STATS_LEN,
SSS_TOOL_GET_NIC_STATS_STRING,
SSS_TOOL_GET_NIC_STATS_INFO,
SSS_TOOL_GET_PF_ID,
SSS_TOOL_NIC_RSVD4,
SSS_TOOL_NIC_RSVD5,
SSS_TOOL_DCB_QOS_INFO,
SSS_TOOL_DCB_PFC_STATE,
SSS_TOOL_DCB_ETS_STATE,
SSS_TOOL_DCB_STATE,
SSS_TOOL_QOS_DEV,
SSS_TOOL_GET_QOS_COS,
SSS_TOOL_GET_ULD_DEV_NAME,
SSS_TOOL_GET_TX_TIMEOUT,
SSS_TOOL_SET_TX_TIMEOUT,
SSS_TOOL_RSS_CFG = 0x40,
SSS_TOOL_RSS_INDIR,
SSS_TOOL_PORT_ID,
SSS_TOOL_GET_FUNC_CAP = 0x50,
SSS_TOOL_GET_XSFP_PRESENT = 0x51,
SSS_TOOL_GET_XSFP_INFO = 0x52,
SSS_TOOL_DEV_NAME_TEST = 0x53,
SSS_TOOL_GET_WIN_STAT = 0x60,
SSS_TOOL_WIN_CSR_READ = 0x61,
SSS_TOOL_WIN_CSR_WRITE = 0x62,
SSS_TOOL_WIN_API_CMD_RD = 0x63,
SSS_TOOL_VM_COMPAT_TEST = 0xFF
};
struct sss_tool_show_item {
char name[SSS_TOOL_SHOW_ITEM_LEN];
u8 hexadecimal; /* 0: decimal , 1: Hexadecimal */
u8 rsvd[7];
u64 value;
};
struct sss_tool_drv_version_info {
char ver[SSS_TOOL_VERSION_INFO_LEN];
};
#endif /* _SSS_NIC_MT_H_ */
......@@ -2,10 +2,14 @@
# Copyright (c) 2023 3SNIC
#
SYS_TIME=$(shell date +%Y-%m-%d_%H:%M:%S)
ccflags-y += -D __TIME_STR__=\"$(SYS_TIME)\"
ccflags-y += -I$(srctree)/drivers/net/ethernet/3snic/sssnic/include
ccflags-y += -I$(srctree)/drivers/net/ethernet/3snic/sssnic/include/hw
ccflags-y += -I$(srctree)/drivers/net/ethernet/3snic/sssnic/include/kernel
ccflags-y += -I$(srctree)/drivers/net/ethernet/3snic/sssnic/nic
ccflags-y += -I$(srctree)/drivers/net/ethernet/3snic/sssnic/nic/tool
ccflags-y += -I$(srctree)/drivers/net/ethernet/3snic/sssnic/nic/include
ccflags-y += -Werror
......@@ -33,4 +37,9 @@ sssnic-y := sss_nic_main.o \
sss_nic_rss_cfg.o \
sss_nic_event.o \
sss_nic_io.o \
sss_nic_netdev_ops_api.o
sss_nic_netdev_ops_api.o \
./tool/sss_tool_nic_func.o \
./tool/sss_tool_nic_dcb.o \
./tool/sss_tool_nic_phy_attr.o \
./tool/sss_tool_nic_qp_info.o \
./tool/sss_tool_nic_stats.o
......@@ -455,4 +455,6 @@ struct sss_nic_mag_cfg {
struct mutex sfp_mutex; /* mutex used for copy sfp info */
};
#define SSSNIC_PF_LIMIT_BW_MAX 100
#endif
......@@ -45,9 +45,9 @@ struct sss_nic_sq_stats {
u64 dma_map_err;
u64 unknown_tunnel_proto;
u64 frag_size_zero;
u64 frag_len_overflow;
u64 rsvd1;
u64 rsvd2;
u64 rsvd3;
#ifdef HAVE_NDO_GET_STATS64
struct u64_stats_sync stats_sync;
......
......@@ -99,5 +99,7 @@ void sss_nic_io_deinit(struct sss_nic_dev *nic_dev);
int sss_nic_rq_hw_pc_info(struct sss_nic_dev *nic_dev,
struct sss_nic_rq_pc_info *out_info, u16 num_qps, u16 wqe_type);
int sss_nic_set_pf_rate(struct sss_nic_dev *nic_dev, u8 speed);
#endif
......@@ -104,4 +104,6 @@ int sss_nic_set_settings_to_hw(struct sss_nic_dev *nic_dev,
int sssnic_set_link_settings(struct net_device *netdev,
u8 autoneg, u32 speed);
void sss_nic_get_io_stats(const struct sss_nic_dev *nic_dev, void *stats);
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册