Commit e8e3f2da authored by Dazhao Lao's avatar Dazhao Lao
Browse files

[PATCH OLK-5.10] RDMA/hns: Support configure and query the CNP DSCP through sysfs

driver inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IAL7SX



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

Support configure and query the CNP DSCP through sysfs.

example:
$ echo 1 > /sys/class/infiniband/hns_2/ports/1/cc_param/cnp_pri_param/
enable
$ cat /sys/class/infiniband/hns_2/ports/1/cc_param/cnp_pri_param/enable
$ 1
$ echo 22 > /sys/class/infiniband/hns_2/ports/1/cc_param/cnp_pri_param/dscp
$ cat /sys/class/infiniband/hns_2/ports/1/cc_param/cnp_pri_param/dscp
$ 22

Restriction
1.Only HIP10 is supported.
2.Only the main PF is supported.
3.ROH only.
4.The DSCP value ranges from 0 to 63. The default value is 0.
5.The CNP enabling value has two enable values: 0 (select from the
QPC) and 1 (select from this configuration). The default value is 0.
6.When the CNP DSCP configuration enabling value is 0, the configured
DSCP value is invalid and the error code EPERM is returned.

Signed-off-by: default avatarDazhao Lao <laodazhao@huawei.com>
Reviewed-by: default avatarKe Chen <chenke54@huawei.com>
parent 0baa48ea
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -115,6 +115,8 @@
#define HNS_ROCE_MAX_CQ_COUNT 0xFFFF
#define HNS_ROCE_MAX_CQ_PERIOD 0xFFFF

#define MAIN_PF_FUNC_ID 0

enum {
	SERV_TYPE_RC,
	SERV_TYPE_UC,
@@ -179,6 +181,10 @@ enum {
	HNS_ROCE_CAP_FLAG_POE                   = BIT(27),
};

enum {
	FW_CAP_FLAG_CNP_PRI = BIT(3),
};

#define HNS_ROCE_DB_TYPE_COUNT			2
#define HNS_ROCE_DB_UNIT_SIZE			4

@@ -1102,6 +1108,14 @@ struct hns_roce_hw {
	int (*query_scc_param)(struct hns_roce_dev *hr_dev, u8 port_num,
			       enum hns_roce_scc_algo alog);
	int (*cfg_poe_ch)(struct hns_roce_dev *hr_dev, u32 index, u64 poe_addr);
	int (*config_cnp_pri_param)(struct hns_roce_dev *hr_dev, u8 port_num);
	int (*query_cnp_pri_param)(struct hns_roce_dev *hr_dev, u8 port_num);
};

struct hns_roce_cnp_pri_param {
	__le32 param;
	struct hns_roce_dev *hr_dev;
	u8 port_num;
};

#define HNS_ROCE_SCC_PARAM_SIZE 4
@@ -1120,6 +1134,7 @@ struct hns_roce_port {
	u8 port_num;
	struct kobject kobj;
	struct hns_roce_scc_param *scc_param;
	struct hns_roce_cnp_pri_param *cnp_pri_param;
};

struct hns_roce_mtr_node {
+48 −0
Original line number Diff line number Diff line
@@ -7376,6 +7376,52 @@ static enum hns_roce_opcode_type scc_opcode[] = {
	HNS_ROCE_OPC_CFG_DIP_PARAM,
};

static int hns_roce_v2_config_cnp_pri_param(struct hns_roce_dev *hr_dev,
					    u8 port_num)
{
	struct hns_roce_cnp_pri_param *cnp_pri_param;
	struct hns_roce_cmq_desc desc;
	struct hns_roce_port *pdata;
	int ret;

	hns_roce_cmq_setup_basic_desc(&desc, HNS_ROCE_OPC_CFG_CNP_PRI, false);
	pdata = &hr_dev->port_data[port_num - 1];
	cnp_pri_param = pdata->cnp_pri_param;
	desc.data[0] = cnp_pri_param->param;

	ret = hns_roce_cmq_send(hr_dev, &desc, 1);
	if (ret)
		ibdev_err_ratelimited(&hr_dev->ib_dev,
				      "failed to configure cnp pri param, opcode: 0x%x, ret = %d.\n",
				      le16_to_cpu(desc.opcode), ret);
	return ret;
}


static int hns_roce_v2_query_cnp_pri_param(struct hns_roce_dev *hr_dev,
					   u8 port_num)
{
	struct hns_roce_cnp_pri_param *cnp_pri_param;
	struct hns_roce_cmq_desc desc;
	struct hns_roce_port *pdata;
	int ret;

	hns_roce_cmq_setup_basic_desc(&desc, HNS_ROCE_OPC_CFG_CNP_PRI, true);
	ret = hns_roce_cmq_send(hr_dev, &desc, 1);
	if (ret) {
		ibdev_err_ratelimited(&hr_dev->ib_dev,
				      "failed to query cnp pri param, opcode: 0x%x, ret = %d.\n",
				      le16_to_cpu(desc.opcode), ret);
		return ret;
	}

	pdata = &hr_dev->port_data[port_num - 1];
	cnp_pri_param = pdata->cnp_pri_param;
	cnp_pri_param->param = desc.data[0];

	return 0;
}

static int hns_roce_v2_config_scc_param(struct hns_roce_dev *hr_dev,
					u8 port_num,
					enum hns_roce_scc_algo algo)
@@ -7566,6 +7612,8 @@ static const struct hns_roce_hw hns_roce_hw_v2 = {
	.config_scc_param = hns_roce_v2_config_scc_param,
	.query_scc_param = hns_roce_v2_query_scc_param,
	.cfg_poe_ch = hns_roce_cfg_poe_ch,
	.config_cnp_pri_param = hns_roce_v2_config_cnp_pri_param,
	.query_cnp_pri_param = hns_roce_v2_query_cnp_pri_param,
};

static const struct pci_device_id hns_roce_hw_v2_pci_tbl[] = {
+12 −0
Original line number Diff line number Diff line
@@ -230,6 +230,7 @@ enum hns_roce_opcode_type {
	HNS_ROCE_OPC_CFG_GMV_BT				= 0x8510,
	HNS_ROCE_OPC_SYNC_MB				= 0x8511,
	HNS_ROCE_QUERY_RAM_ECC				= 0x8513,
	HNS_ROCE_OPC_CFG_CNP_PRI			= 0x8514,
	HNS_SWITCH_PARAMETER_CFG			= 0x1033,
	HNS_ROCE_OPC_SET_BOND_INFO			= 0x8601,
	HNS_ROCE_OPC_CLEAR_BOND_INFO			= 0x8602,
@@ -1555,6 +1556,17 @@ struct hns_roce_wqe_atomic_seg {
	__le64          cmp_data;
};

#define HNS_ROCE_CNP_PRI_ENABLE_BIT_OFS 0
#define HNS_ROCE_CNP_PRI_ENABLE_BIT_SZ 1
#define HNS_ROCE_CNP_PRI_ENABLE_BIT_MASK GENMASK(0, 0)
#define HNS_ROCE_CNP_PRI_ENABLE_MAX 1

#define HNS_ROCE_CNP_PRI_DSCP_BIT_OFS (HNS_ROCE_CNP_PRI_ENABLE_BIT_OFS + \
					HNS_ROCE_CNP_PRI_ENABLE_BIT_SZ)
#define HNS_ROCE_CNP_PRI_DSCP_BIT_SZ 6
#define HNS_ROCE_CNP_PRI_DSCP_BIT_MASK GENMASK(6, 1)
#define HNS_ROCE_CNP_PRI_DSCP_MAX 63

#define HNS_ROCE_DCQCN_AI_OFS 0
#define HNS_ROCE_DCQCN_AI_SZ sizeof(u16)
#define HNS_ROCE_DCQCN_AI_MAX ((u16)(~0U))
+161 −0
Original line number Diff line number Diff line
@@ -26,6 +26,41 @@ static void scc_param_config_work(struct work_struct *work)
				     scc_param->algo_type);
}

static void get_default_cnp_pri_param(struct hns_roce_dev *hr_dev,
				  struct hns_roce_port *pdata)
{
	if (hr_dev->is_vf || hr_dev->pci_dev->revision <= PCI_REVISION_ID_HIP09)
		return;

	if (hr_dev->mac_type != HNAE3_MAC_ROH ||
	    hr_dev->func_id != MAIN_PF_FUNC_ID)
		return;

	if (!(hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_QP_FLOW_CTRL) ||
	    !(hr_dev->caps.fw_cap & FW_CAP_FLAG_CNP_PRI))
		return;

	hr_dev->hw->query_cnp_pri_param(hr_dev, pdata->port_num);
}

static int alloc_cnp_pri_param(struct hns_roce_dev *hr_dev,
			       struct hns_roce_port *pdata)
{
	struct hns_roce_cnp_pri_param *cnp_pri_param;

	cnp_pri_param = kvzalloc(sizeof(*cnp_pri_param), GFP_KERNEL);
	if (!cnp_pri_param)
		return -ENOMEM;

	cnp_pri_param->hr_dev = hr_dev;
	cnp_pri_param->port_num = pdata->port_num;
	pdata->cnp_pri_param = cnp_pri_param;

	get_default_cnp_pri_param(hr_dev, pdata);

	return 0;
}

static void get_default_scc_param(struct hns_roce_dev *hr_dev,
				  struct hns_roce_port *pdata)
{
@@ -77,6 +112,14 @@ struct hns_port_cc_attr {
	u32 min;
};

struct hns_port_cnp_pri_attr {
	struct hns_port_attribute port_attr;
	u32 bit_offset;
	u32 bit_size;
	u32 bit_mask;
	u32 max;
};

static int scc_attr_check(struct hns_port_cc_attr *scc_attr)
{
	if (WARN_ON(scc_attr->size > sizeof(u32)))
@@ -87,6 +130,63 @@ static int scc_attr_check(struct hns_port_cc_attr *scc_attr)
	return 0;
}

static ssize_t cnp_pri_attr_show(struct hns_roce_port *pdata,
				 struct hns_port_attribute *attr, char *buf)
{
	struct hns_port_cnp_pri_attr *cnp_pri_attr =
		container_of(attr, struct hns_port_cnp_pri_attr, port_attr);
	struct hns_roce_cnp_pri_param *cnp_pri_param;
	u32 param;
	u32 val;

	cnp_pri_param = pdata->cnp_pri_param;
	param = le32_to_cpu(cnp_pri_param->param);
	val = (param & cnp_pri_attr->bit_mask) >> cnp_pri_attr->bit_offset;

	return sysfs_emit(buf, "%u\n", val);
}

static ssize_t cnp_pri_attr_store(struct hns_roce_port *pdata,
				  struct hns_port_attribute *attr,
				  const char *buf, size_t count)
{
	struct hns_port_cnp_pri_attr *cnp_pri_attr =
		container_of(attr, struct hns_port_cnp_pri_attr, port_attr);
	struct hns_roce_cnp_pri_param *cnp_pri_param;
	struct hns_roce_dev *hr_dev;
	__le32 param_bak;
	u32 param;
	u32 val;
	int ret;

	ret = kstrtou32(buf, 0, &val);
	if (ret)
		return ret;

	if (val > cnp_pri_attr->max)
		return -EINVAL;

	cnp_pri_param = pdata->cnp_pri_param;
	param = le32_to_cpu(cnp_pri_param->param);
	if (cnp_pri_attr->bit_offset != HNS_ROCE_CNP_PRI_ENABLE_BIT_OFS &&
	    !(param & HNS_ROCE_CNP_PRI_ENABLE_BIT_MASK))
		return -EPERM;

	param = param & (~cnp_pri_attr->bit_mask);
	val = (val << cnp_pri_attr->bit_offset) | param;
	param_bak = cnp_pri_param->param;
	cnp_pri_param->param = cpu_to_le32(val);
	hr_dev = cnp_pri_param->hr_dev;

	ret = hr_dev->hw->config_cnp_pri_param(hr_dev, cnp_pri_param->port_num);
	if (ret) {
		cnp_pri_param->param = param_bak;
		return ret;
	}

	return count;
}

static ssize_t scc_attr_show(struct hns_roce_port *pdata,
			     struct hns_port_attribute *attr, char *buf)
{
@@ -151,6 +251,27 @@ static ssize_t scc_attr_store(struct hns_roce_port *pdata,
	return count;
}

static umode_t cnp_pri_param_is_visible(struct kobject *kobj,
				     struct attribute *attr, int i)
{
	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->pci_dev->revision <= PCI_REVISION_ID_HIP09)
		return 0;

	if (hr_dev->mac_type != HNAE3_MAC_ROH ||
	    hr_dev->func_id != MAIN_PF_FUNC_ID)
		return 0;

	if (!(hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_QP_FLOW_CTRL) ||
	    !(hr_dev->caps.fw_cap & FW_CAP_FLAG_CNP_PRI))
		return 0;

	return 0644;
}

static umode_t scc_attr_is_visible(struct kobject *kobj,
				   struct attribute *attr, int i)
{
@@ -172,6 +293,37 @@ static umode_t scc_attr_is_visible(struct kobject *kobj,
	return 0644;
}

#define __HNS_CNP_PRI_ATTR(_name, _offset, _size, _mask, _max) {		\
	.port_attr = __ATTR(_name, 0644, cnp_pri_attr_show,  cnp_pri_attr_store),	\
	.bit_offset = _offset,							\
	.bit_size = _size,								\
	.bit_mask = _mask,								\
	.max = _max,								\
}

#define HNS_PORT_CNP_PRI_ATTR_RW(_name, NAME)			\
	struct hns_port_cnp_pri_attr hns_roce_port_attr_cnp_pri_##_name =	\
	__HNS_CNP_PRI_ATTR(_name,		\
			HNS_ROCE_CNP_PRI_##NAME##_BIT_OFS,			\
			HNS_ROCE_CNP_PRI_##NAME##_BIT_SZ,			\
			HNS_ROCE_CNP_PRI_##NAME##_BIT_MASK,			\
			HNS_ROCE_CNP_PRI_##NAME##_MAX)

HNS_PORT_CNP_PRI_ATTR_RW(enable, ENABLE);
HNS_PORT_CNP_PRI_ATTR_RW(dscp, DSCP);

static struct attribute *cnp_pri_param_attrs[] = {
	&hns_roce_port_attr_cnp_pri_enable.port_attr.attr,
	&hns_roce_port_attr_cnp_pri_dscp.port_attr.attr,
	NULL,
};

static const struct attribute_group cnp_pri_param_group = {
	.name = "cnp_pri_param",
	.attrs = cnp_pri_param_attrs,
	.is_visible = cnp_pri_param_is_visible,
};

#define __HNS_SCC_ATTR(_name, _type, _offset, _size, _min, _max) {		\
	.port_attr = __ATTR(_name, 0644, scc_attr_show,  scc_attr_store),	\
	.algo_type = _type,							\
@@ -330,6 +482,7 @@ const struct attribute_group *hns_attr_port_groups[] = {
	&ldcp_cc_param_group,
	&hc3_cc_param_group,
	&dip_cc_param_group,
	&cnp_pri_param_group,
	NULL,
};

@@ -368,6 +521,7 @@ static void hns_roce_port_release(struct kobject *kobj)
		container_of(kobj, struct hns_roce_port, kobj);

	kfree(pdata->scc_param);
	kvfree(pdata->cnp_pri_param);
}

static const struct sysfs_ops hns_roce_port_ops = {
@@ -420,6 +574,13 @@ int hns_roce_create_port_files(struct ib_device *ibdev, u8 port_num,
		goto fail_group;
	}

	ret = alloc_cnp_pri_param(hr_dev, pdata);
	if (ret) {
		dev_err(hr_dev->dev, "alloc cnp pri param failed, ret = %d!\n",
			ret);
		goto fail_group;
	}

	return ret;

fail_group: