Unverified Commit 5184a907 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!11010 roh/rdma: Support rdma_cm and cnp configure

parents 4ebd7cfe b6b9d85b
Loading
Loading
Loading
Loading
+16 −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

@@ -983,6 +989,7 @@ struct hns_roce_caps {
	u8		congest_type;
	u8		default_congest_type;
	u8              poe_ch_num;
	u32		fw_cap;
};

enum hns_roce_device_state {
@@ -1101,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
@@ -1119,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 {
+145 −4
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
#include <rdma/ib_umem.h>
#include <rdma/uverbs_ioctl.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_mad.h>

#include "hnae3.h"
#include "hclge_main.h"
@@ -554,7 +555,6 @@ static inline int set_ud_wqe(struct hns_roce_qp *qp,
			     void *wqe, unsigned int *sge_idx,
			     unsigned int owner_bit)
{
	struct hns_roce_dev *hr_dev = to_hr_dev(qp->ibqp.device);
	struct hns_roce_ah *ah = to_hr_ah(ud_wr(wr)->ah);
	struct hns_roce_v2_ud_send_wqe *ud_sq_wqe = wqe;
	unsigned int curr_idx = *sge_idx;
@@ -588,9 +588,6 @@ static inline int set_ud_wqe(struct hns_roce_qp *qp,
	if (ret)
		return ret;

	if (hr_dev->mac_type == HNAE3_MAC_ROH && qp->ibqp.qp_type == IB_QPT_GSI)
		ud_sq_wqe->dmac[0] = 0xFF;

	qp->sl = to_hr_ah(ud_wr(wr)->ah)->av.sl;

	set_extend_sge(qp, wr->sg_list, &curr_idx, valid_num_sge);
@@ -1822,6 +1819,7 @@ static int hns_roce_query_fw_ver(struct hns_roce_dev *hr_dev)

	resp = (struct hns_roce_query_fw_info *)desc.data;
	hr_dev->caps.fw_ver = (u64)(le32_to_cpu(resp->fw_ver));
	hr_dev->caps.fw_cap = le32_to_cpu(resp->fw_cap);

	return 0;
}
@@ -4397,6 +4395,100 @@ static int fill_recv_wc(struct ib_wc *wc, struct hns_roce_v2_cqe *cqe)
	return 0;
}

struct ib_mad_list_head {
	struct list_head list;
	struct ib_cqe cqe;
	struct ib_mad_queue *mad_queue;
};

struct ib_mad_private_header {
	struct ib_mad_list_head mad_list;
	struct ib_mad_recv_wc recv_wc;
	struct ib_wc wc;
	u64 mapping;
} __packed;

struct ib_mad_private {
	struct ib_mad_private_header header;
	size_t mad_size;
	struct ib_grh grh;
	u8 mad[];
} __packed;

static inline struct ib_mad_list_head *to_mad_list_head(void *cqe)
{
	return container_of((struct ib_cqe *)cqe, struct ib_mad_list_head, cqe);
}

static inline struct ib_mad_private_header
			*to_mad_private_header(struct ib_mad_list_head *mad_list)
{
	return container_of(mad_list, struct ib_mad_private_header, mad_list);
}

static inline struct ib_mad_private
			*to_mad_private(struct ib_mad_private_header *header)
{
	return container_of(header, struct ib_mad_private, header);
}

static bool find_first_in4_gid(struct hns_roce_dev *hr_dev,
			       struct hns_roce_qp *qp, union ib_gid *gid)
{
	int i;

	/*
	 * The performance of querying the gid table each time is not good,
	 * but if we want to cache the gid, we need to add a synchronization
	 * mechanism which will lead to an increase in software complexity.
	 * Considering that CM does not belong to the IO path and does not
	 * have high performance requirements, we use this simpler solution.
	 */
	for (i = 0; i < hr_dev->caps.gid_table_len[qp->port]; i += 1) {
		if (rdma_query_gid(&hr_dev->ib_dev, qp->port + 1, i, gid))
			continue;
		/* link local addr is not a valid in4 addr */
		if (rdma_link_local_addr((struct in6_addr *)gid->raw))
			continue;

		return true;
	}

	return false;
}

static void hns_roh_restore_grh(struct hns_roce_dev *hr_dev,
				struct hns_roce_qp *qp, struct ib_wc *wc,
				struct hns_roce_v2_cqe *cqe)
{
#define IPV4_PREFIX_MASK 0xFF000000
	struct ib_mad_list_head *mad_list = to_mad_list_head((void *)wc->wr_id);
	struct ib_mad_private_header *header = to_mad_private_header(mad_list);
	struct ib_mad_private *mad_private = to_mad_private(header);
	u32 smac = hr_reg_read(cqe, CQE_SMAC_L);
	union rdma_network_hdr *hdr;
	union ib_gid gid = {};
	u32 daddr;

	if (hr_dev->mac_type != HNAE3_MAC_ROH || qp->ibqp.qp_type != IB_QPT_GSI)
		return;

	if (!find_first_in4_gid(hr_dev, qp, &gid))
		return;

	/* RoH only support IPv4, so interface_id won't bigger than U32_MAX */
	daddr = (u32)be64_to_cpu(gid.global.interface_id);
	/*
	 * For RoH, only the lower 24 bit is valid, it needs to get the first
	 * 8 bit from the daddr
	 */
	smac = smac | (daddr & IPV4_PREFIX_MASK);

	hdr = (union rdma_network_hdr *)&mad_private->grh;
	hdr->roce4grh.saddr = cpu_to_be32(smac);
	hdr->roce4grh.daddr = cpu_to_be32(daddr);
}

static int hns_roce_v2_poll_one(struct hns_roce_cq *hr_cq,
				struct hns_roce_qp **cur_qp, struct ib_wc *wc)
{
@@ -4449,6 +4541,7 @@ static int hns_roce_v2_poll_one(struct hns_roce_cq *hr_cq,
		} else {
			wq = &qp->rq;
			wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)];
			hns_roh_restore_grh(hr_dev, qp, wc, cqe);
			++wq->tail;
		}

@@ -7375,6 +7468,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)
@@ -7565,6 +7704,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[] = {
+17 −2
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,
@@ -736,7 +737,8 @@ struct hns_roce_v2_cqe {
#define CQE_LCL_QPN CQE_FIELD_LOC(119, 96)
#define CQE_SUB_STATUS CQE_FIELD_LOC(127, 120)
#define CQE_BYTE_CNT CQE_FIELD_LOC(159, 128)
#define CQE_SMAC CQE_FIELD_LOC(207, 160)
#define CQE_SMAC_L CQE_FIELD_LOC(191, 160)
#define CQE_SMAC_H CQE_FIELD_LOC(207, 192)
#define CQE_PORT_TYPE CQE_FIELD_LOC(209, 208)
#define CQE_VID CQE_FIELD_LOC(221, 210)
#define CQE_VID_VLD CQE_FIELD_LOC(222, 222)
@@ -1008,7 +1010,9 @@ struct hns_roce_query_version {

struct hns_roce_query_fw_info {
	__le32 fw_ver;
	__le32 rsv[5];
	__le32 rsv[3];
	__le32 fw_cap;
	__le32 rsv1[1];
};

struct hns_roce_func_clear {
@@ -1553,6 +1557,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: