Commit 0e40dc2f authored by Yangyang Li's avatar Yangyang Li Committed by Jason Gunthorpe
Browse files

RDMA/hns: Add timer allocation support for hip08



This patch adds qpc timer and cqc timer allocation support for hardware
timeout retransmission in kernel space driver.

Signed-off-by: default avatarYangyang Li <liyangyang20@huawei.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent aa84fa18
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -75,6 +75,10 @@ enum {
	HNS_ROCE_CMD_DESTROY_MPT_BT1	= 0x29,
	HNS_ROCE_CMD_DESTROY_MPT_BT2	= 0x2a,

	/* CQC TIMER commands */
	HNS_ROCE_CMD_WRITE_CQC_TIMER_BT0 = 0x23,
	HNS_ROCE_CMD_READ_CQC_TIMER_BT0  = 0x27,

	/* MPT commands */
	HNS_ROCE_CMD_QUERY_MPT		= 0x62,

@@ -89,6 +93,10 @@ enum {
	HNS_ROCE_CMD_DESTROY_SRQC_BT1	= 0x39,
	HNS_ROCE_CMD_DESTROY_SRQC_BT2	= 0x3a,

	/* QPC TIMER commands */
	HNS_ROCE_CMD_WRITE_QPC_TIMER_BT0 = 0x33,
	HNS_ROCE_CMD_READ_QPC_TIMER_BT0  = 0x37,

	/* EQC commands */
	HNS_ROCE_CMD_CREATE_AEQC	= 0x80,
	HNS_ROCE_CMD_MODIFY_AEQC	= 0x81,
+14 −0
Original line number Diff line number Diff line
@@ -732,6 +732,8 @@ struct hns_roce_caps {
	u32		max_extend_sg;
	int		num_qps;	/* 256k */
	int             reserved_qps;
	int		num_qpc_timer;
	int		num_cqc_timer;
	u32		max_srq_sg;
	int		num_srqs;
	u32		max_wqes;	/* 16k */
@@ -772,6 +774,8 @@ struct hns_roce_caps {
	int		trrl_entry_sz;
	int		cqc_entry_sz;
	int		sccc_entry_sz;
	int		qpc_timer_entry_sz;
	int		cqc_timer_entry_sz;
	int		srqc_entry_sz;
	int		idx_entry_sz;
	u32		pbl_ba_pg_sz;
@@ -781,8 +785,10 @@ struct hns_roce_caps {
	int		ceqe_depth;
	enum ib_mtu	max_mtu;
	u32		qpc_bt_num;
	u32		qpc_timer_bt_num;
	u32		srqc_bt_num;
	u32		cqc_bt_num;
	u32		cqc_timer_bt_num;
	u32		mpt_bt_num;
	u32		sccc_bt_num;
	u32		qpc_ba_pg_sz;
@@ -803,6 +809,12 @@ struct hns_roce_caps {
	u32		sccc_ba_pg_sz;
	u32		sccc_buf_pg_sz;
	u32		sccc_hop_num;
	u32		qpc_timer_ba_pg_sz;
	u32		qpc_timer_buf_pg_sz;
	u32		qpc_timer_hop_num;
	u32		cqc_timer_ba_pg_sz;
	u32		cqc_timer_buf_pg_sz;
	u32		cqc_timer_hop_num;
	u32		cqe_ba_pg_sz;
	u32		cqe_buf_pg_sz;
	u32		cqe_hop_num;
@@ -932,6 +944,8 @@ struct hns_roce_dev {
	struct hns_roce_srq_table srq_table;
	struct hns_roce_qp_table  qp_table;
	struct hns_roce_eq_table  eq_table;
	struct hns_roce_hem_table  qpc_timer_table;
	struct hns_roce_hem_table  cqc_timer_table;

	int			cmd_mod;
	int			loop_idc;
+42 −0
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ bool hns_roce_check_whether_mhop(struct hns_roce_dev *hr_dev, u32 type)
	    (hr_dev->caps.cqc_hop_num && type == HEM_TYPE_CQC) ||
	    (hr_dev->caps.srqc_hop_num && type == HEM_TYPE_SRQC) ||
	    (hr_dev->caps.sccc_hop_num && type == HEM_TYPE_SCCC) ||
	    (hr_dev->caps.qpc_timer_hop_num && type == HEM_TYPE_QPC_TIMER) ||
	    (hr_dev->caps.cqc_timer_hop_num && type == HEM_TYPE_CQC_TIMER) ||
	    (hr_dev->caps.cqe_hop_num && type == HEM_TYPE_CQE) ||
	    (hr_dev->caps.mtt_hop_num && type == HEM_TYPE_MTT) ||
	    (hr_dev->caps.srqwqe_hop_num && type == HEM_TYPE_SRQWQE) ||
@@ -134,6 +136,22 @@ int hns_roce_calc_hem_mhop(struct hns_roce_dev *hr_dev,
		mhop->ba_l0_num = hr_dev->caps.sccc_bt_num;
		mhop->hop_num = hr_dev->caps.sccc_hop_num;
		break;
	case HEM_TYPE_QPC_TIMER:
		mhop->buf_chunk_size = 1 << (hr_dev->caps.qpc_timer_buf_pg_sz
					     + PAGE_SHIFT);
		mhop->bt_chunk_size = 1 << (hr_dev->caps.qpc_timer_ba_pg_sz
					    + PAGE_SHIFT);
		mhop->ba_l0_num = hr_dev->caps.qpc_timer_bt_num;
		mhop->hop_num = hr_dev->caps.qpc_timer_hop_num;
		break;
	case HEM_TYPE_CQC_TIMER:
		mhop->buf_chunk_size = 1 << (hr_dev->caps.cqc_timer_buf_pg_sz
					     + PAGE_SHIFT);
		mhop->bt_chunk_size = 1 << (hr_dev->caps.cqc_timer_ba_pg_sz
					    + PAGE_SHIFT);
		mhop->ba_l0_num = hr_dev->caps.cqc_timer_bt_num;
		mhop->hop_num = hr_dev->caps.cqc_timer_hop_num;
		break;
	case HEM_TYPE_SRQC:
		mhop->buf_chunk_size = 1 << (hr_dev->caps.srqc_buf_pg_sz
					     + PAGE_SHIFT);
@@ -602,6 +620,7 @@ out:
	mutex_unlock(&table->mutex);
	return ret;
}
EXPORT_SYMBOL_GPL(hns_roce_table_get);

static void hns_roce_table_mhop_put(struct hns_roce_dev *hr_dev,
				    struct hns_roce_hem_table *table,
@@ -744,6 +763,7 @@ void hns_roce_table_put(struct hns_roce_dev *hr_dev,

	mutex_unlock(&table->mutex);
}
EXPORT_SYMBOL_GPL(hns_roce_table_put);

void *hns_roce_table_find(struct hns_roce_dev *hr_dev,
			  struct hns_roce_hem_table *table,
@@ -921,6 +941,22 @@ int hns_roce_init_hem_table(struct hns_roce_dev *hr_dev,
			num_bt_l0 = hr_dev->caps.sccc_bt_num;
			hop_num = hr_dev->caps.sccc_hop_num;
			break;
		case HEM_TYPE_QPC_TIMER:
			buf_chunk_size = 1 << (hr_dev->caps.qpc_timer_buf_pg_sz
					+ PAGE_SHIFT);
			bt_chunk_size = 1 << (hr_dev->caps.qpc_timer_ba_pg_sz
					+ PAGE_SHIFT);
			num_bt_l0 = hr_dev->caps.qpc_timer_bt_num;
			hop_num = hr_dev->caps.qpc_timer_hop_num;
			break;
		case HEM_TYPE_CQC_TIMER:
			buf_chunk_size = 1 << (hr_dev->caps.cqc_timer_buf_pg_sz
					+ PAGE_SHIFT);
			bt_chunk_size = 1 << (hr_dev->caps.cqc_timer_ba_pg_sz
					+ PAGE_SHIFT);
			num_bt_l0 = hr_dev->caps.cqc_timer_bt_num;
			hop_num = hr_dev->caps.cqc_timer_hop_num;
			break;
		case HEM_TYPE_SRQC:
			buf_chunk_size = 1 << (hr_dev->caps.srqc_buf_pg_sz
					+ PAGE_SHIFT);
@@ -1098,6 +1134,12 @@ void hns_roce_cleanup_hem(struct hns_roce_dev *hr_dev)
		hns_roce_cleanup_hem_table(hr_dev,
					   &hr_dev->srq_table.table);
	hns_roce_cleanup_hem_table(hr_dev, &hr_dev->cq_table.table);
	if (hr_dev->caps.qpc_timer_entry_sz)
		hns_roce_cleanup_hem_table(hr_dev,
					   &hr_dev->qpc_timer_table);
	if (hr_dev->caps.cqc_timer_entry_sz)
		hns_roce_cleanup_hem_table(hr_dev,
					   &hr_dev->cqc_timer_table);
	if (hr_dev->caps.sccc_entry_sz)
		hns_roce_cleanup_hem_table(hr_dev,
					   &hr_dev->qp_table.sccc_table);
+2 −0
Original line number Diff line number Diff line
@@ -45,6 +45,8 @@ enum {
	HEM_TYPE_CQC,
	HEM_TYPE_SRQC,
	HEM_TYPE_SCCC,
	HEM_TYPE_QPC_TIMER,
	HEM_TYPE_CQC_TIMER,

	 /* UNMAP HEM */
	HEM_TYPE_MTT,
+101 −2
Original line number Diff line number Diff line
@@ -1085,6 +1085,41 @@ static int hns_roce_query_pf_resource(struct hns_roce_dev *hr_dev)
	return 0;
}

static int hns_roce_query_pf_timer_resource(struct hns_roce_dev *hr_dev)
{
	struct hns_roce_pf_timer_res_a *req_a;
	struct hns_roce_cmq_desc desc[2];
	int ret, i;

	for (i = 0; i < 2; i++) {
		hns_roce_cmq_setup_basic_desc(&desc[i],
					      HNS_ROCE_OPC_QUERY_PF_TIMER_RES,
					      true);

		if (i == 0)
			desc[i].flag |= cpu_to_le16(HNS_ROCE_CMD_FLAG_NEXT);
		else
			desc[i].flag &= ~cpu_to_le16(HNS_ROCE_CMD_FLAG_NEXT);
	}

	ret = hns_roce_cmq_send(hr_dev, desc, 2);
	if (ret)
		return ret;

	req_a = (struct hns_roce_pf_timer_res_a *)desc[0].data;

	hr_dev->caps.qpc_timer_bt_num =
				roce_get_field(req_a->qpc_timer_bt_idx_num,
					PF_RES_DATA_1_PF_QPC_TIMER_BT_NUM_M,
					PF_RES_DATA_1_PF_QPC_TIMER_BT_NUM_S);
	hr_dev->caps.cqc_timer_bt_num =
				roce_get_field(req_a->cqc_timer_bt_idx_num,
					PF_RES_DATA_2_PF_CQC_TIMER_BT_NUM_M,
					PF_RES_DATA_2_PF_CQC_TIMER_BT_NUM_S);

	return 0;
}

static int hns_roce_set_vf_switch_param(struct hns_roce_dev *hr_dev,
						  int vf_id)
{
@@ -1315,6 +1350,16 @@ static int hns_roce_v2_profile(struct hns_roce_dev *hr_dev)
		return ret;
	}

	if (hr_dev->pci_dev->revision == 0x21) {
		ret = hns_roce_query_pf_timer_resource(hr_dev);
		if (ret) {
			dev_err(hr_dev->dev,
				"Query pf timer resource fail, ret = %d.\n",
				ret);
			return ret;
		}
	}

	ret = hns_roce_alloc_vf_resource(hr_dev);
	if (ret) {
		dev_err(hr_dev->dev, "Allocate vf resource fail, ret = %d.\n",
@@ -1439,6 +1484,17 @@ static int hns_roce_v2_profile(struct hns_roce_dev *hr_dev)
			       HNS_ROCE_CAP_FLAG_SRQ |
			       HNS_ROCE_CAP_FLAG_QP_FLOW_CTRL;

		caps->num_qpc_timer	  = HNS_ROCE_V2_MAX_QPC_TIMER_NUM;
		caps->qpc_timer_entry_sz  = HNS_ROCE_V2_QPC_TIMER_ENTRY_SZ;
		caps->qpc_timer_ba_pg_sz  = 0;
		caps->qpc_timer_buf_pg_sz = 0;
		caps->qpc_timer_hop_num   = HNS_ROCE_HOP_NUM_0;
		caps->num_cqc_timer	  = HNS_ROCE_V2_MAX_CQC_TIMER_NUM;
		caps->cqc_timer_entry_sz  = HNS_ROCE_V2_CQC_TIMER_ENTRY_SZ;
		caps->cqc_timer_ba_pg_sz  = 0;
		caps->cqc_timer_buf_pg_sz = 0;
		caps->cqc_timer_hop_num   = HNS_ROCE_HOP_NUM_0;

		caps->sccc_entry_sz	= HNS_ROCE_V2_SCCC_ENTRY_SZ;
		caps->sccc_ba_pg_sz	= 0;
		caps->sccc_buf_pg_sz    = 0;
@@ -1644,7 +1700,8 @@ static void hns_roce_free_link_table(struct hns_roce_dev *hr_dev,
static int hns_roce_v2_init(struct hns_roce_dev *hr_dev)
{
	struct hns_roce_v2_priv *priv = hr_dev->priv;
	int ret;
	int qpc_count, cqc_count;
	int ret, i;

	/* TSQ includes SQ doorbell and ack doorbell */
	ret = hns_roce_init_link_table(hr_dev, TSQ_LINK_TABLE);
@@ -1659,8 +1716,40 @@ static int hns_roce_v2_init(struct hns_roce_dev *hr_dev)
		goto err_tpq_init_failed;
	}

	/* Alloc memory for QPC Timer buffer space chunk*/
	for (qpc_count = 0; qpc_count < hr_dev->caps.qpc_timer_bt_num;
	     qpc_count++) {
		ret = hns_roce_table_get(hr_dev, &hr_dev->qpc_timer_table,
					 qpc_count);
		if (ret) {
			dev_err(hr_dev->dev, "QPC Timer get failed\n");
			goto err_qpc_timer_failed;
		}
	}

	/* Alloc memory for CQC Timer buffer space chunk*/
	for (cqc_count = 0; cqc_count < hr_dev->caps.cqc_timer_bt_num;
	     cqc_count++) {
		ret = hns_roce_table_get(hr_dev, &hr_dev->cqc_timer_table,
					 cqc_count);
		if (ret) {
			dev_err(hr_dev->dev, "CQC Timer get failed\n");
			goto err_cqc_timer_failed;
		}
	}

	return 0;

err_cqc_timer_failed:
	for (i = 0; i < cqc_count; i++)
		hns_roce_table_put(hr_dev, &hr_dev->cqc_timer_table, i);

err_qpc_timer_failed:
	for (i = 0; i < qpc_count; i++)
		hns_roce_table_put(hr_dev, &hr_dev->qpc_timer_table, i);

	hns_roce_free_link_table(hr_dev, &priv->tpq);

err_tpq_init_failed:
	hns_roce_free_link_table(hr_dev, &priv->tsq);

@@ -2699,6 +2788,12 @@ static int hns_roce_v2_set_hem(struct hns_roce_dev *hr_dev,
	case HEM_TYPE_SCCC:
		op = HNS_ROCE_CMD_WRITE_SCCC_BT0;
		break;
	case HEM_TYPE_QPC_TIMER:
		op = HNS_ROCE_CMD_WRITE_QPC_TIMER_BT0;
		break;
	case HEM_TYPE_CQC_TIMER:
		op = HNS_ROCE_CMD_WRITE_CQC_TIMER_BT0;
		break;
	default:
		dev_warn(dev, "Table %d not to be written by mailbox!\n",
			 table->type);
@@ -2763,6 +2858,8 @@ static int hns_roce_v2_clear_hem(struct hns_roce_dev *hr_dev,
		op = HNS_ROCE_CMD_DESTROY_CQC_BT0;
		break;
	case HEM_TYPE_SCCC:
	case HEM_TYPE_QPC_TIMER:
	case HEM_TYPE_CQC_TIMER:
		break;
	case HEM_TYPE_SRQC:
		op = HNS_ROCE_CMD_DESTROY_SRQC_BT0;
@@ -2773,7 +2870,9 @@ static int hns_roce_v2_clear_hem(struct hns_roce_dev *hr_dev,
		return 0;
	}

	if (table->type == HEM_TYPE_SCCC)
	if (table->type == HEM_TYPE_SCCC ||
	    table->type == HEM_TYPE_QPC_TIMER ||
	    table->type == HEM_TYPE_CQC_TIMER)
		return 0;

	op += step_idx;
Loading