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

!475 Support congestion control algorithm parameter configuration

Merge Pull Request from: @stinft 
 
hns roce support 4 congestion control algorithms. Each algorihm
involves multiple parameters. This patch add port sysfs directory
for each algorithm, which allows users to modify the parameters
of these algorithms.
bugzilla:#I6J5O7 
 
Link:https://gitee.com/openeuler/kernel/pulls/475 

Reviewed-by: Yue Haibing <yuehaibing@huawei.com> 
Reviewed-by: Jialin Zhang <zhangjialin11@huawei.com> 
Signed-off-by: Jialin Zhang <zhangjialin11@huawei.com> 
......@@ -10,7 +10,7 @@ ccflags-y += -I $(srctree)/drivers/net/ethernet/hisilicon/hns3/hns3_common
hns-roce-objs := hns_roce_main.o hns_roce_cmd.o hns_roce_pd.o \
hns_roce_ah.o hns_roce_hem.o hns_roce_mr.o hns_roce_qp.o \
hns_roce_cq.o hns_roce_alloc.o hns_roce_db.o hns_roce_srq.o hns_roce_restrack.o \
hns_roce_bond.o hns_roce_dca.o hns_roce_debugfs.o
hns_roce_bond.o hns_roce_dca.o hns_roce_debugfs.o hns_roce_sysfs.o
ifdef CONFIG_INFINIBAND_HNS_HIP08
hns-roce-hw-v2-objs := hns_roce_hw_v2.o $(hns-roce-objs)
......
......@@ -767,11 +767,19 @@ struct hns_roce_eq_table {
struct hns_roce_eq *eq;
};
enum hns_roce_scc_algo {
HNS_ROCE_SCC_ALGO_DCQCN = 0,
HNS_ROCE_SCC_ALGO_LDCP,
HNS_ROCE_SCC_ALGO_HC3,
HNS_ROCE_SCC_ALGO_DIP,
HNS_ROCE_SCC_ALGO_TOTAL,
};
enum cong_type {
CONG_TYPE_DCQCN,
CONG_TYPE_LDCP,
CONG_TYPE_HC3,
CONG_TYPE_DIP,
CONG_TYPE_DCQCN = 1 << HNS_ROCE_SCC_ALGO_DCQCN,
CONG_TYPE_LDCP = 1 << HNS_ROCE_SCC_ALGO_LDCP,
CONG_TYPE_HC3 = 1 << HNS_ROCE_SCC_ALGO_HC3,
CONG_TYPE_DIP = 1 << HNS_ROCE_SCC_ALGO_DIP,
};
struct hns_roce_caps {
......@@ -1016,6 +1024,28 @@ struct hns_roce_hw {
int (*bond_init)(struct hns_roce_dev *hr_dev);
bool (*bond_is_active)(struct hns_roce_dev *hr_dev);
struct net_device *(*get_bond_netdev)(struct hns_roce_dev *hr_dev);
int (*config_scc_param)(struct hns_roce_dev *hr_dev, u8 port_num,
enum hns_roce_scc_algo algo);
int (*query_scc_param)(struct hns_roce_dev *hr_dev, u8 port_num,
enum hns_roce_scc_algo alog);
};
#define HNS_ROCE_SCC_PARAM_SIZE 4
struct hns_roce_scc_param {
__le32 param[HNS_ROCE_SCC_PARAM_SIZE];
u32 lifespan;
unsigned long timestamp;
enum hns_roce_scc_algo algo_type;
struct delayed_work scc_cfg_dwork;
struct hns_roce_dev *hr_dev;
u8 port_num;
};
struct hns_roce_port {
struct hns_roce_dev *hr_dev;
u8 port_num;
struct kobject kobj;
struct hns_roce_scc_param *scc_param;
};
struct hns_roce_dev {
......@@ -1094,6 +1124,7 @@ struct hns_roce_dev {
struct delayed_work bond_work;
struct hns_roce_bond_group *bond_grp;
struct netdev_lag_lower_state_info slave_state;
struct hns_roce_port port_data[HNS_ROCE_MAX_PORTS];
atomic64_t *dfx_cnt;
};
......@@ -1379,4 +1410,7 @@ struct hns_user_mmap_entry *
hns_roce_user_mmap_entry_insert(struct ib_ucontext *ucontext, u64 address,
size_t length,
enum hns_roce_mmap_type mmap_type);
int hns_roce_create_port_files(struct ib_device *ibdev, u8 port_num,
struct kobject *kobj);
void hns_roce_unregister_sysfs(struct hns_roce_dev *hr_dev);
#endif /* _HNS_ROCE_DEVICE_H */
......@@ -7146,6 +7146,81 @@ static void hns_roce_v2_cleanup_eq_table(struct hns_roce_dev *hr_dev)
kfree(eq_table->eq);
}
static enum hns_roce_opcode_type scc_opcode[] = {
HNS_ROCE_OPC_CFG_DCQCN_PARAM,
HNS_ROCE_OPC_CFG_LDCP_PARAM,
HNS_ROCE_OPC_CFG_HC3_PARAM,
HNS_ROCE_OPC_CFG_DIP_PARAM,
};
static int hns_roce_v2_config_scc_param(struct hns_roce_dev *hr_dev,
u8 port_num,
enum hns_roce_scc_algo algo)
{
struct hns_roce_scc_param *scc_param;
struct hns_roce_cmq_desc desc;
struct hns_roce_port *pdata;
int ret;
if (port_num > hr_dev->caps.num_ports) {
ibdev_err_ratelimited(&hr_dev->ib_dev,
"invalid port num %u.\n", port_num);
return -ENODEV;
}
if (algo >= HNS_ROCE_SCC_ALGO_TOTAL) {
ibdev_err_ratelimited(&hr_dev->ib_dev, "invalid SCC algo.\n");
return -EINVAL;
}
hns_roce_cmq_setup_basic_desc(&desc, scc_opcode[algo], false);
pdata = &hr_dev->port_data[port_num - 1];
scc_param = &pdata->scc_param[algo];
memcpy(&desc.data, scc_param, sizeof(scc_param->param));
ret = hns_roce_cmq_send(hr_dev, &desc, 1);
if (ret)
ibdev_err_ratelimited(&hr_dev->ib_dev,
"failed to configure scc param, opcode: 0x%x, ret = %d.\n",
le16_to_cpu(desc.opcode), ret);
return ret;
}
static int hns_roce_v2_query_scc_param(struct hns_roce_dev *hr_dev,
u8 port_num, enum hns_roce_scc_algo algo)
{
struct hns_roce_scc_param *scc_param;
struct hns_roce_cmq_desc desc;
struct hns_roce_port *pdata;
int ret;
if (port_num > hr_dev->caps.num_ports) {
ibdev_err_ratelimited(&hr_dev->ib_dev,
"invalid port num %u.\n", port_num);
return -ENODEV;
}
if (algo >= HNS_ROCE_SCC_ALGO_TOTAL) {
ibdev_err_ratelimited(&hr_dev->ib_dev, "invalid SCC algo.\n");
return -EINVAL;
}
hns_roce_cmq_setup_basic_desc(&desc, scc_opcode[algo], true);
ret = hns_roce_cmq_send(hr_dev, &desc, 1);
if (ret) {
ibdev_err_ratelimited(&hr_dev->ib_dev,
"failed to query scc param, opcode: 0x%x, ret = %d.\n",
le16_to_cpu(desc.opcode), ret);
return ret;
}
pdata = &hr_dev->port_data[port_num - 1];
scc_param = &pdata->scc_param[algo];
memcpy(scc_param, &desc.data, sizeof(scc_param->param));
return 0;
}
static const struct ib_device_ops hns_roce_v2_dev_ops = {
.destroy_qp = hns_roce_v2_destroy_qp,
.modify_cq = hns_roce_v2_modify_cq,
......@@ -7198,6 +7273,8 @@ static const struct hns_roce_hw hns_roce_hw_v2 = {
.bond_is_active = hns_roce_bond_is_active,
.get_bond_netdev = hns_roce_get_bond_netdev,
.query_hw_counter = hns_roce_hw_v2_query_counter,
.config_scc_param = hns_roce_v2_config_scc_param,
.query_scc_param = hns_roce_v2_query_scc_param,
};
static const struct pci_device_id hns_roce_hw_v2_pci_tbl[] = {
......
......@@ -227,6 +227,10 @@ enum {
enum hns_roce_opcode_type {
HNS_QUERY_FW_VER = 0x0001,
HNS_QUERY_MAC_TYPE = 0x0389,
HNS_ROCE_OPC_CFG_DCQCN_PARAM = 0x1A80,
HNS_ROCE_OPC_CFG_LDCP_PARAM = 0x1A81,
HNS_ROCE_OPC_CFG_HC3_PARAM = 0x1A82,
HNS_ROCE_OPC_CFG_DIP_PARAM = 0x1A83,
HNS_ROCE_OPC_QUERY_HW_VER = 0x8000,
HNS_ROCE_OPC_CFG_GLOBAL_PARAM = 0x8001,
HNS_ROCE_OPC_ALLOC_PF_RES = 0x8004,
......@@ -1468,6 +1472,134 @@ struct hns_roce_wqe_atomic_seg {
__le64 cmp_data;
};
#define HNS_ROCE_DCQCN_AI_OFS 0
#define HNS_ROCE_DCQCN_AI_SZ sizeof(u16)
#define HNS_ROCE_DCQCN_AI_MAX ((u16)(~0U))
#define HNS_ROCE_DCQCN_F_OFS (HNS_ROCE_DCQCN_AI_OFS + HNS_ROCE_DCQCN_AI_SZ)
#define HNS_ROCE_DCQCN_F_SZ sizeof(u8)
#define HNS_ROCE_DCQCN_F_MAX ((u8)(~0U))
#define HNS_ROCE_DCQCN_TKP_OFS (HNS_ROCE_DCQCN_F_OFS + HNS_ROCE_DCQCN_F_SZ)
#define HNS_ROCE_DCQCN_TKP_SZ sizeof(u8)
#define HNS_ROCE_DCQCN_TKP_MAX 15
#define HNS_ROCE_DCQCN_TMP_OFS (HNS_ROCE_DCQCN_TKP_OFS + HNS_ROCE_DCQCN_TKP_SZ)
#define HNS_ROCE_DCQCN_TMP_SZ sizeof(u16)
#define HNS_ROCE_DCQCN_TMP_MAX 15
#define HNS_ROCE_DCQCN_ALP_OFS (HNS_ROCE_DCQCN_TMP_OFS + HNS_ROCE_DCQCN_TMP_SZ)
#define HNS_ROCE_DCQCN_ALP_SZ sizeof(u16)
#define HNS_ROCE_DCQCN_ALP_MAX ((u16)(~0U))
#define HNS_ROCE_DCQCN_MAX_SPEED_OFS (HNS_ROCE_DCQCN_ALP_OFS + \
HNS_ROCE_DCQCN_ALP_SZ)
#define HNS_ROCE_DCQCN_MAX_SPEED_SZ sizeof(u32)
#define HNS_ROCE_DCQCN_MAX_SPEED_MAX ((u32)(~0U))
#define HNS_ROCE_DCQCN_G_OFS (HNS_ROCE_DCQCN_MAX_SPEED_OFS + \
HNS_ROCE_DCQCN_MAX_SPEED_SZ)
#define HNS_ROCE_DCQCN_G_SZ sizeof(u8)
#define HNS_ROCE_DCQCN_G_MAX 15
#define HNS_ROCE_DCQCN_AL_OFS (HNS_ROCE_DCQCN_G_OFS + HNS_ROCE_DCQCN_G_SZ)
#define HNS_ROCE_DCQCN_AL_SZ sizeof(u8)
#define HNS_ROCE_DCQCN_AL_MAX ((u8)(~0U))
#define HNS_ROCE_DCQCN_CNP_TIME_OFS (HNS_ROCE_DCQCN_AL_OFS + \
HNS_ROCE_DCQCN_AL_SZ)
#define HNS_ROCE_DCQCN_CNP_TIME_SZ sizeof(u8)
#define HNS_ROCE_DCQCN_CNP_TIME_MAX ((u8)(~0U))
#define HNS_ROCE_DCQCN_ASHIFT_OFS (HNS_ROCE_DCQCN_CNP_TIME_OFS + \
HNS_ROCE_DCQCN_CNP_TIME_SZ)
#define HNS_ROCE_DCQCN_ASHIFT_SZ sizeof(u8)
#define HNS_ROCE_DCQCN_ASHIFT_MAX 15
#define HNS_ROCE_DCQCN_LIFESPAN_OFS (HNS_ROCE_DCQCN_ASHIFT_OFS + \
HNS_ROCE_DCQCN_ASHIFT_SZ)
#define HNS_ROCE_DCQCN_LIFESPAN_SZ sizeof(u32)
#define HNS_ROCE_DCQCN_LIFESPAN_MAX 1000
#define HNS_ROCE_LDCP_CWD0_OFS 0
#define HNS_ROCE_LDCP_CWD0_SZ sizeof(u32)
#define HNS_ROCE_LDCP_CWD0_MAX ((u32)(~0U))
#define HNS_ROCE_LDCP_ALPHA_OFS (HNS_ROCE_LDCP_CWD0_OFS + HNS_ROCE_LDCP_CWD0_SZ)
#define HNS_ROCE_LDCP_ALPHA_SZ sizeof(u8)
#define HNS_ROCE_LDCP_ALPHA_MAX ((u8)(~0U))
#define HNS_ROCE_LDCP_GAMMA_OFS (HNS_ROCE_LDCP_ALPHA_OFS + \
HNS_ROCE_LDCP_ALPHA_SZ)
#define HNS_ROCE_LDCP_GAMMA_SZ sizeof(u8)
#define HNS_ROCE_LDCP_GAMMA_MAX ((u8)(~0U))
#define HNS_ROCE_LDCP_BETA_OFS (HNS_ROCE_LDCP_GAMMA_OFS + \
HNS_ROCE_LDCP_GAMMA_SZ)
#define HNS_ROCE_LDCP_BETA_SZ sizeof(u8)
#define HNS_ROCE_LDCP_BETA_MAX ((u8)(~0U))
#define HNS_ROCE_LDCP_ETA_OFS (HNS_ROCE_LDCP_BETA_OFS + HNS_ROCE_LDCP_BETA_SZ)
#define HNS_ROCE_LDCP_ETA_SZ sizeof(u8)
#define HNS_ROCE_LDCP_ETA_MAX ((u8)(~0U))
#define HNS_ROCE_LDCP_LIFESPAN_OFS (4 * sizeof(u32))
#define HNS_ROCE_LDCP_LIFESPAN_SZ sizeof(u32)
#define HNS_ROCE_LDCP_LIFESPAN_MAX 1000
#define HNS_ROCE_HC3_INITIAL_WINDOW_OFS 0
#define HNS_ROCE_HC3_INITIAL_WINDOW_SZ sizeof(u32)
#define HNS_ROCE_HC3_INITIAL_WINDOW_MAX ((u32)(~0U))
#define HNS_ROCE_HC3_BANDWIDTH_OFS (HNS_ROCE_HC3_INITIAL_WINDOW_OFS + \
HNS_ROCE_HC3_INITIAL_WINDOW_SZ)
#define HNS_ROCE_HC3_BANDWIDTH_SZ sizeof(u32)
#define HNS_ROCE_HC3_BANDWIDTH_MAX ((u32)(~0U))
#define HNS_ROCE_HC3_QLEN_SHIFT_OFS (HNS_ROCE_HC3_BANDWIDTH_OFS + \
HNS_ROCE_HC3_BANDWIDTH_SZ)
#define HNS_ROCE_HC3_QLEN_SHIFT_SZ sizeof(u8)
#define HNS_ROCE_HC3_QLEN_SHIFT_MAX ((u8)(~0U))
#define HNS_ROCE_HC3_PORT_USAGE_SHIFT_OFS (HNS_ROCE_HC3_QLEN_SHIFT_OFS + \
HNS_ROCE_HC3_QLEN_SHIFT_SZ)
#define HNS_ROCE_HC3_PORT_USAGE_SHIFT_SZ sizeof(u8)
#define HNS_ROCE_HC3_PORT_USAGE_SHIFT_MAX ((u8)(~0U))
#define HNS_ROCE_HC3_OVER_PERIOD_OFS (HNS_ROCE_HC3_PORT_USAGE_SHIFT_OFS + \
HNS_ROCE_HC3_PORT_USAGE_SHIFT_SZ)
#define HNS_ROCE_HC3_OVER_PERIOD_SZ sizeof(u8)
#define HNS_ROCE_HC3_OVER_PERIOD_MAX ((u8)(~0U))
#define HNS_ROCE_HC3_MAX_STAGE_OFS (HNS_ROCE_HC3_OVER_PERIOD_OFS + \
HNS_ROCE_HC3_OVER_PERIOD_SZ)
#define HNS_ROCE_HC3_MAX_STAGE_SZ sizeof(u8)
#define HNS_ROCE_HC3_MAX_STAGE_MAX ((u8)(~0U))
#define HNS_ROCE_HC3_GAMMA_SHIFT_OFS (HNS_ROCE_HC3_MAX_STAGE_OFS + \
HNS_ROCE_HC3_MAX_STAGE_SZ)
#define HNS_ROCE_HC3_GAMMA_SHIFT_SZ sizeof(u8)
#define HNS_ROCE_HC3_GAMMA_SHIFT_MAX 15
#define HNS_ROCE_HC3_LIFESPAN_OFS (4 * sizeof(u32))
#define HNS_ROCE_HC3_LIFESPAN_SZ sizeof(u32)
#define HNS_ROCE_HC3_LIFESPAN_MAX 1000
#define HNS_ROCE_DIP_AI_OFS 0
#define HNS_ROCE_DIP_AI_SZ sizeof(u16)
#define HNS_ROCE_DIP_AI_MAX ((u16)(~0U))
#define HNS_ROCE_DIP_F_OFS (HNS_ROCE_DIP_AI_OFS + HNS_ROCE_DIP_AI_SZ)
#define HNS_ROCE_DIP_F_SZ sizeof(u8)
#define HNS_ROCE_DIP_F_MAX ((u8)(~0U))
#define HNS_ROCE_DIP_TKP_OFS (HNS_ROCE_DIP_F_OFS + HNS_ROCE_DIP_F_SZ)
#define HNS_ROCE_DIP_TKP_SZ sizeof(u8)
#define HNS_ROCE_DIP_TKP_MAX 15
#define HNS_ROCE_DIP_TMP_OFS (HNS_ROCE_DIP_TKP_OFS + HNS_ROCE_DIP_TKP_SZ)
#define HNS_ROCE_DIP_TMP_SZ sizeof(u16)
#define HNS_ROCE_DIP_TMP_MAX 15
#define HNS_ROCE_DIP_ALP_OFS (HNS_ROCE_DIP_TMP_OFS + HNS_ROCE_DIP_TMP_SZ)
#define HNS_ROCE_DIP_ALP_SZ sizeof(u16)
#define HNS_ROCE_DIP_ALP_MAX ((u16)(~0U))
#define HNS_ROCE_DIP_MAX_SPEED_OFS (HNS_ROCE_DIP_ALP_OFS + HNS_ROCE_DIP_ALP_SZ)
#define HNS_ROCE_DIP_MAX_SPEED_SZ sizeof(u32)
#define HNS_ROCE_DIP_MAX_SPEED_MAX ((u32)(~0U))
#define HNS_ROCE_DIP_G_OFS (HNS_ROCE_DIP_MAX_SPEED_OFS + \
HNS_ROCE_DIP_MAX_SPEED_SZ)
#define HNS_ROCE_DIP_G_SZ sizeof(u8)
#define HNS_ROCE_DIP_G_MAX 15
#define HNS_ROCE_DIP_AL_OFS (HNS_ROCE_DIP_G_OFS + HNS_ROCE_DIP_G_SZ)
#define HNS_ROCE_DIP_AL_SZ sizeof(u8)
#define HNS_ROCE_DIP_AL_MAX ((u8)(~0U))
#define HNS_ROCE_DIP_CNP_TIME_OFS (HNS_ROCE_DIP_AL_OFS + HNS_ROCE_DIP_AL_SZ)
#define HNS_ROCE_DIP_CNP_TIME_SZ sizeof(u8)
#define HNS_ROCE_DIP_CNP_TIME_MAX ((u8)(~0U))
#define HNS_ROCE_DIP_ASHIFT_OFS (HNS_ROCE_DIP_CNP_TIME_OFS + \
HNS_ROCE_DIP_CNP_TIME_SZ)
#define HNS_ROCE_DIP_ASHIFT_SZ sizeof(u8)
#define HNS_ROCE_DIP_ASHIFT_MAX 15
#define HNS_ROCE_DIP_LIFESPAN_OFS (HNS_ROCE_DIP_ASHIFT_OFS + \
HNS_ROCE_DIP_ASHIFT_SZ)
#define HNS_ROCE_DIP_LIFESPAN_SZ sizeof(u32)
#define HNS_ROCE_DIP_LIFESPAN_MAX 1000
struct hns_roce_sccc_clr {
__le32 qpn;
__le32 rsv[5];
......
......@@ -870,6 +870,7 @@ static const struct ib_device_ops hns_roce_dev_ops = {
.reg_user_mr = hns_roce_reg_user_mr,
.alloc_hw_stats = hns_roce_alloc_hw_port_stats,
.get_hw_stats = hns_roce_get_hw_stats,
.init_port = hns_roce_create_port_files,
INIT_RDMA_OBJ_SIZE(ib_ah, hns_roce_ah, ibah),
INIT_RDMA_OBJ_SIZE(ib_cq, hns_roce_cq, ib_cq),
......@@ -1441,6 +1442,7 @@ int hns_roce_init(struct hns_roce_dev *hr_dev)
void hns_roce_exit(struct hns_roce_dev *hr_dev)
{
hns_roce_unregister_sysfs(hr_dev);
hns_roce_unregister_device(hr_dev);
hns_roce_unregister_debugfs(hr_dev);
......
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/*
* Copyright (c) 2023 Hisilicon Limited.
*/
#include "hnae3.h"
#include "hns_roce_device.h"
#include "hns_roce_hw_v2.h"
struct hns_port_attribute {
struct attribute attr;
ssize_t (*show)(struct hns_roce_port *pdata,
struct hns_port_attribute *attr, char *buf);
ssize_t (*store)(struct hns_roce_port *pdata,
struct hns_port_attribute *attr, const char *buf,
size_t count);
};
static void scc_param_config_work(struct work_struct *work)
{
struct hns_roce_scc_param *scc_param = container_of(work,
struct hns_roce_scc_param, scc_cfg_dwork.work);
struct hns_roce_dev *hr_dev = scc_param->hr_dev;
hr_dev->hw->config_scc_param(hr_dev, scc_param->port_num,
scc_param->algo_type);
}
static int alloc_scc_param(struct hns_roce_dev *hr_dev,
struct hns_roce_port *pdata)
{
struct hns_roce_scc_param *scc_param;
int i;
scc_param = kcalloc(HNS_ROCE_SCC_ALGO_TOTAL, sizeof(*scc_param),
GFP_KERNEL);
if (!scc_param)
return -ENOMEM;
for (i = 0; i < HNS_ROCE_SCC_ALGO_TOTAL; i++) {
scc_param[i].algo_type = i;
scc_param[i].timestamp = jiffies;
scc_param[i].hr_dev = hr_dev;
scc_param[i].port_num = pdata->port_num;
INIT_DELAYED_WORK(&scc_param[i].scc_cfg_dwork,
scc_param_config_work);
}
pdata->scc_param = scc_param;
return 0;
}
struct hns_port_cc_attr {
struct hns_port_attribute port_attr;
enum hns_roce_scc_algo algo_type;
u32 offset;
u32 size;
u32 max;
u32 min;
};
static int scc_attr_check(struct hns_port_cc_attr *scc_attr)
{
if (WARN_ON(scc_attr->size > sizeof(u32)))
return -EINVAL;
if (WARN_ON(scc_attr->algo_type >= HNS_ROCE_SCC_ALGO_TOTAL))
return -EINVAL;
return 0;
}
static ssize_t scc_attr_show(struct hns_roce_port *pdata,
struct hns_port_attribute *attr, char *buf)
{
struct hns_port_cc_attr *scc_attr =
container_of(attr, struct hns_port_cc_attr, port_attr);
struct hns_roce_scc_param *scc_param;
unsigned long exp_time;
__le32 val = 0;
int ret;
ret = scc_attr_check(scc_attr);
if (ret)
return ret;
scc_param = &pdata->scc_param[scc_attr->algo_type];
/* Only HW param need be queried */
if (scc_attr->offset < offsetof(typeof(*scc_param), lifespan)) {
exp_time = scc_param->timestamp +
msecs_to_jiffies(scc_param->lifespan);
if (time_is_before_eq_jiffies(exp_time)) {
scc_param->timestamp = jiffies;
pdata->hr_dev->hw->query_scc_param(pdata->hr_dev,
pdata->port_num, scc_attr->algo_type);
}
}
memcpy(&val, (void *)scc_param + scc_attr->offset, scc_attr->size);
return sysfs_emit(buf, "%u\n", le32_to_cpu(val));
}
static ssize_t scc_attr_store(struct hns_roce_port *pdata,
struct hns_port_attribute *attr,
const char *buf, size_t count)
{
struct hns_port_cc_attr *scc_attr =
container_of(attr, struct hns_port_cc_attr, port_attr);
struct hns_roce_scc_param *scc_param;
unsigned long lifespan_jiffies;
unsigned long exp_time;
__le32 attr_val;
u32 val;
int ret;
ret = scc_attr_check(scc_attr);
if (ret)
return ret;
if (kstrtou32(buf, 0, &val))
return -EINVAL;
if (val > scc_attr->max || val < scc_attr->min)
return -EINVAL;
attr_val = cpu_to_le32(val);
scc_param = &pdata->scc_param[scc_attr->algo_type];
memcpy((void *)scc_param + scc_attr->offset, &attr_val,
scc_attr->size);
/* lifespan is only used for driver */
if (scc_attr->offset >= offsetof(typeof(*scc_param), lifespan))
return count;
lifespan_jiffies = msecs_to_jiffies(scc_param->lifespan);
exp_time = scc_param->timestamp + lifespan_jiffies;
if (time_is_before_eq_jiffies(exp_time)) {
scc_param->timestamp = jiffies;
queue_delayed_work(pdata->hr_dev->irq_workq,
&scc_param->scc_cfg_dwork, lifespan_jiffies);
}
return count;
}
static umode_t scc_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int i)
{
struct hns_port_attribute *port_attr =
container_of(attr, struct hns_port_attribute, attr);
struct hns_port_cc_attr *scc_attr =
container_of(port_attr, struct hns_port_cc_attr, port_attr);
struct hns_roce_port *pdata =
container_of(kobj, struct hns_roce_port, kobj);
struct hns_roce_dev *hr_dev = pdata->hr_dev;
if (hr_dev->is_vf ||
!(hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_QP_FLOW_CTRL))
return 0;
if (!(hr_dev->caps.cong_type & (1 << scc_attr->algo_type)))
return 0;
return 0644;
}
#define __HNS_SCC_ATTR(_name, _type, _offset, _size, _min, _max) { \
.port_attr = __ATTR(_name, 0644, scc_attr_show, scc_attr_store), \
.algo_type = _type, \
.offset = _offset, \
.size = _size, \
.min = _min, \
.max = _max, \
}
#define HNS_PORT_DCQCN_CC_ATTR_RW(_name, NAME) \
struct hns_port_cc_attr hns_roce_port_attr_dcqcn_##_name = \
__HNS_SCC_ATTR(_name, HNS_ROCE_SCC_ALGO_DCQCN, \
HNS_ROCE_DCQCN_##NAME##_OFS, \
HNS_ROCE_DCQCN_##NAME##_SZ, \
0, HNS_ROCE_DCQCN_##NAME##_MAX)
HNS_PORT_DCQCN_CC_ATTR_RW(ai, AI);
HNS_PORT_DCQCN_CC_ATTR_RW(f, F);
HNS_PORT_DCQCN_CC_ATTR_RW(tkp, TKP);
HNS_PORT_DCQCN_CC_ATTR_RW(tmp, TMP);
HNS_PORT_DCQCN_CC_ATTR_RW(alp, ALP);
HNS_PORT_DCQCN_CC_ATTR_RW(max_speed, MAX_SPEED);
HNS_PORT_DCQCN_CC_ATTR_RW(g, G);
HNS_PORT_DCQCN_CC_ATTR_RW(al, AL);
HNS_PORT_DCQCN_CC_ATTR_RW(cnp_time, CNP_TIME);
HNS_PORT_DCQCN_CC_ATTR_RW(ashift, ASHIFT);
HNS_PORT_DCQCN_CC_ATTR_RW(lifespan, LIFESPAN);
static struct attribute *dcqcn_param_attrs[] = {
&hns_roce_port_attr_dcqcn_ai.port_attr.attr,
&hns_roce_port_attr_dcqcn_f.port_attr.attr,
&hns_roce_port_attr_dcqcn_tkp.port_attr.attr,
&hns_roce_port_attr_dcqcn_tmp.port_attr.attr,
&hns_roce_port_attr_dcqcn_alp.port_attr.attr,
&hns_roce_port_attr_dcqcn_max_speed.port_attr.attr,
&hns_roce_port_attr_dcqcn_g.port_attr.attr,
&hns_roce_port_attr_dcqcn_al.port_attr.attr,
&hns_roce_port_attr_dcqcn_cnp_time.port_attr.attr,
&hns_roce_port_attr_dcqcn_ashift.port_attr.attr,
&hns_roce_port_attr_dcqcn_lifespan.port_attr.attr,
NULL,
};
static const struct attribute_group dcqcn_cc_param_group = {
.name = "dcqcn_cc_param",
.attrs = dcqcn_param_attrs,
.is_visible = scc_attr_is_visible,
};
#define HNS_PORT_LDCP_CC_ATTR_RW(_name, NAME) \
struct hns_port_cc_attr hns_roce_port_attr_ldcp_##_name = \
__HNS_SCC_ATTR(_name, HNS_ROCE_SCC_ALGO_LDCP, \
HNS_ROCE_LDCP_##NAME##_OFS, \
HNS_ROCE_LDCP_##NAME##_SZ, \
0, HNS_ROCE_LDCP_##NAME##_MAX)
HNS_PORT_LDCP_CC_ATTR_RW(cwd0, CWD0);
HNS_PORT_LDCP_CC_ATTR_RW(alpha, ALPHA);
HNS_PORT_LDCP_CC_ATTR_RW(gamma, GAMMA);
HNS_PORT_LDCP_CC_ATTR_RW(beta, BETA);
HNS_PORT_LDCP_CC_ATTR_RW(eta, ETA);
HNS_PORT_LDCP_CC_ATTR_RW(lifespan, LIFESPAN);
static struct attribute *ldcp_param_attrs[] = {
&hns_roce_port_attr_ldcp_cwd0.port_attr.attr,
&hns_roce_port_attr_ldcp_alpha.port_attr.attr,
&hns_roce_port_attr_ldcp_gamma.port_attr.attr,
&hns_roce_port_attr_ldcp_beta.port_attr.attr,
&hns_roce_port_attr_ldcp_eta.port_attr.attr,
&hns_roce_port_attr_ldcp_lifespan.port_attr.attr,
NULL,
};
static const struct attribute_group ldcp_cc_param_group = {
.name = "ldcp_cc_param",
.attrs = ldcp_param_attrs,
.is_visible = scc_attr_is_visible,
};
#define HNS_PORT_HC3_CC_ATTR_RW(_name, NAME) \
struct hns_port_cc_attr hns_roce_port_attr_hc3_##_name = \
__HNS_SCC_ATTR(_name, HNS_ROCE_SCC_ALGO_HC3, \
HNS_ROCE_HC3_##NAME##_OFS, \
HNS_ROCE_HC3_##NAME##_SZ, \
0, HNS_ROCE_HC3_##NAME##_MAX)
HNS_PORT_HC3_CC_ATTR_RW(initial_window, INITIAL_WINDOW);
HNS_PORT_HC3_CC_ATTR_RW(bandwidth, BANDWIDTH);
HNS_PORT_HC3_CC_ATTR_RW(qlen_shift, QLEN_SHIFT);
HNS_PORT_HC3_CC_ATTR_RW(port_usage_shift, PORT_USAGE_SHIFT);
HNS_PORT_HC3_CC_ATTR_RW(over_period, OVER_PERIOD);
HNS_PORT_HC3_CC_ATTR_RW(max_stage, MAX_STAGE);
HNS_PORT_HC3_CC_ATTR_RW(gamma_shift, GAMMA_SHIFT);
HNS_PORT_HC3_CC_ATTR_RW(lifespan, LIFESPAN);
static struct attribute *hc3_param_attrs[] = {
&hns_roce_port_attr_hc3_initial_window.port_attr.attr,
&hns_roce_port_attr_hc3_bandwidth.port_attr.attr,
&hns_roce_port_attr_hc3_qlen_shift.port_attr.attr,
&hns_roce_port_attr_hc3_port_usage_shift.port_attr.attr,
&hns_roce_port_attr_hc3_over_period.port_attr.attr,
&hns_roce_port_attr_hc3_max_stage.port_attr.attr,
&hns_roce_port_attr_hc3_gamma_shift.port_attr.attr,
&hns_roce_port_attr_hc3_lifespan.port_attr.attr,
NULL,
};
static const struct attribute_group hc3_cc_param_group = {
.name = "hc3_cc_param",
.attrs = hc3_param_attrs,
.is_visible = scc_attr_is_visible,
};
#define HNS_PORT_DIP_CC_ATTR_RW(_name, NAME) \
struct hns_port_cc_attr hns_roce_port_attr_dip_##_name = \
__HNS_SCC_ATTR(_name, HNS_ROCE_SCC_ALGO_DIP, \
HNS_ROCE_DIP_##NAME##_OFS, \
HNS_ROCE_DIP_##NAME##_SZ, \
0, HNS_ROCE_DIP_##NAME##_MAX)
HNS_PORT_DIP_CC_ATTR_RW(ai, AI);
HNS_PORT_DIP_CC_ATTR_RW(f, F);
HNS_PORT_DIP_CC_ATTR_RW(tkp, TKP);
HNS_PORT_DIP_CC_ATTR_RW(tmp, TMP);
HNS_PORT_DIP_CC_ATTR_RW(alp, ALP);
HNS_PORT_DIP_CC_ATTR_RW(max_speed, MAX_SPEED);
HNS_PORT_DIP_CC_ATTR_RW(g, G);
HNS_PORT_DIP_CC_ATTR_RW(al, AL);
HNS_PORT_DIP_CC_ATTR_RW(cnp_time, CNP_TIME);
HNS_PORT_DIP_CC_ATTR_RW(ashift, ASHIFT);
HNS_PORT_DIP_CC_ATTR_RW(lifespan, LIFESPAN);
static struct attribute *dip_param_attrs[] = {
&hns_roce_port_attr_dip_ai.port_attr.attr,
&hns_roce_port_attr_dip_f.port_attr.attr,
&hns_roce_port_attr_dip_tkp.port_attr.attr,
&hns_roce_port_attr_dip_tmp.port_attr.attr,
&hns_roce_port_attr_dip_alp.port_attr.attr,
&hns_roce_port_attr_dip_max_speed.port_attr.attr,
&hns_roce_port_attr_dip_g.port_attr.attr,
&hns_roce_port_attr_dip_al.port_attr.attr,
&hns_roce_port_attr_dip_cnp_time.port_attr.attr,
&hns_roce_port_attr_dip_ashift.port_attr.attr,
&hns_roce_port_attr_dip_lifespan.port_attr.attr,
NULL,
};
static const struct attribute_group dip_cc_param_group = {
.name = "dip_cc_param",
.attrs = dip_param_attrs,
.is_visible = scc_attr_is_visible,
};
const struct attribute_group *hns_attr_port_groups[] = {
&dcqcn_cc_param_group,
&ldcp_cc_param_group,
&hc3_cc_param_group,
&dip_cc_param_group,
NULL,
};
static ssize_t hns_roce_port_attr_show(struct kobject *kobj,
struct attribute *attr, char *buf)
{
struct hns_port_attribute *port_attr =
container_of(attr, struct hns_port_attribute, attr);
struct hns_roce_port *p =
container_of(kobj, struct hns_roce_port, kobj);
if (!port_attr->show)
return -EIO;
return port_attr->show(p, port_attr, buf);
}
static ssize_t hns_roce_port_attr_store(struct kobject *kobj,
struct attribute *attr,
const char *buf, size_t count)
{
struct hns_port_attribute *port_attr =
container_of(attr, struct hns_port_attribute, attr);
struct hns_roce_port *p =
container_of(kobj, struct hns_roce_port, kobj);
if (!port_attr->store)
return -EIO;
return port_attr->store(p, port_attr, buf, count);
}
static void hns_roce_port_release(struct kobject *kobj)
{
struct hns_roce_port *pdata =
container_of(kobj, struct hns_roce_port, kobj);
kfree(pdata->scc_param);
}
static const struct sysfs_ops hns_roce_port_ops = {
.show = hns_roce_port_attr_show,
.store = hns_roce_port_attr_store,
};
static struct kobj_type hns_roce_port_ktype = {
.release = hns_roce_port_release,
.sysfs_ops = &hns_roce_port_ops,
};
int hns_roce_create_port_files(struct ib_device *ibdev, u8 port_num,
struct kobject *kobj)
{
struct hns_roce_dev *hr_dev = to_hr_dev(ibdev);
struct hns_roce_port *pdata;
int ret;
if (!port_num || port_num > hr_dev->caps.num_ports) {
ibdev_err(ibdev, "fail to create port sysfs for invalid port %u.\n",
port_num);
return -ENODEV;
}
pdata = &hr_dev->port_data[port_num - 1];
pdata->hr_dev = hr_dev;
pdata->port_num = port_num;
ret = kobject_init_and_add(&pdata->kobj, &hns_roce_port_ktype,
kobj, "cc_param");
if (ret) {
ibdev_err(ibdev, "fail to create port(%u) sysfs, ret = %d.\n",
port_num, ret);
goto fail_kobj;
}
kobject_uevent(&pdata->kobj, KOBJ_ADD);
ret = sysfs_create_groups(&pdata->kobj, hns_attr_port_groups);
if (ret) {
ibdev_err(ibdev,
"fail to create port(%u) cc param sysfs, ret = %d.\n",
port_num, ret);
goto fail_kobj;
}
ret = alloc_scc_param(hr_dev, pdata);
if (ret) {
dev_err(hr_dev->dev, "alloc scc param failed, ret = %d!\n",
ret);
goto fail_group;
}
return ret;
fail_group:
sysfs_remove_groups(&pdata->kobj, hns_attr_port_groups);
fail_kobj:
kobject_put(&pdata->kobj);
return ret;
}
static void hns_roce_unregister_port_sysfs(struct hns_roce_dev *hr_dev,
u8 port_num)
{
struct hns_roce_port *pdata;
pdata = &hr_dev->port_data[port_num];
sysfs_remove_groups(&pdata->kobj, hns_attr_port_groups);
kobject_put(&pdata->kobj);
}
void hns_roce_unregister_sysfs(struct hns_roce_dev *hr_dev)
{
int i;
for (i = 0; i < hr_dev->caps.num_ports; i++)
hns_roce_unregister_port_sysfs(hr_dev, i);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册