diff mbox series

[for-next] RDMA/hns: Add support of direct wqe

Message ID 1611395717-11081-1-git-send-email-liweihang@huawei.com (mailing list archive)
State Superseded
Headers show
Series [for-next] RDMA/hns: Add support of direct wqe | expand

Commit Message

Weihang Li Jan. 23, 2021, 9:55 a.m. UTC
From: Yixing Liu <liuyixing1@huawei.com>

Direct wqe is a mechanism to fill wqe directly into the hardware. In the
case of light load, the wqe will be filled into pcie bar space of the
hardware, this will reduce one memory access operation and therefore reduce
the latency.

Signed-off-by: Yixing Liu <liuyixing1@huawei.com>
Signed-off-by: Lang Cheng <chenglang@huawei.com>
Signed-off-by: Weihang Li <liweihang@huawei.com>
---
 drivers/infiniband/hw/hns/hns_roce_device.h |  6 ++++
 drivers/infiniband/hw/hns/hns_roce_hw_v2.c  | 44 ++++++++++++++++++++++++++++-
 drivers/infiniband/hw/hns/hns_roce_hw_v2.h  | 14 +++++++++
 3 files changed, 63 insertions(+), 1 deletion(-)

Comments

Weihang Li Jan. 30, 2021, 8:43 a.m. UTC | #1
On 2021/1/23 17:59, Weihang Li wrote:
> From: Yixing Liu <liuyixing1@huawei.com>
> 
> Direct wqe is a mechanism to fill wqe directly into the hardware. In the
> case of light load, the wqe will be filled into pcie bar space of the
> hardware, this will reduce one memory access operation and therefore reduce
> the latency.
> 
> Signed-off-by: Yixing Liu <liuyixing1@huawei.com>
> Signed-off-by: Lang Cheng <chenglang@huawei.com>
> Signed-off-by: Weihang Li <liweihang@huawei.com>
> ---
>  drivers/infiniband/hw/hns/hns_roce_device.h |  6 ++++
>  drivers/infiniband/hw/hns/hns_roce_hw_v2.c  | 44 ++++++++++++++++++++++++++++-
>  drivers/infiniband/hw/hns/hns_roce_hw_v2.h  | 14 +++++++++
>  3 files changed, 63 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
> index c46b330..6abf7d8 100644
> --- a/drivers/infiniband/hw/hns/hns_roce_device.h
> +++ b/drivers/infiniband/hw/hns/hns_roce_device.h
> @@ -90,6 +90,7 @@
>  #define HNS_ROCE_MAX_PORTS			6
>  #define HNS_ROCE_GID_SIZE			16
>  #define HNS_ROCE_SGE_SIZE			16
> +#define HNS_ROCE_DWQE_SIZE			65536
>  
>  #define HNS_ROCE_HOP_NUM_0			0xff
>  
> @@ -644,6 +645,10 @@ struct hns_roce_work {
>  	u32 queue_num;
>  };
>  
> +enum {
> +	HNS_ROCE_QP_CAP_DIRECT_WQE = BIT(5),
> +};
> +
>  struct hns_roce_qp {
>  	struct ib_qp		ibqp;
>  	struct hns_roce_wq	rq;
> @@ -986,6 +991,7 @@ struct hns_roce_dev {
>  	struct mutex            pgdir_mutex;
>  	int			irq[HNS_ROCE_MAX_IRQ_NUM];
>  	u8 __iomem		*reg_base;
> +	void __iomem		*mem_base;
>  	struct hns_roce_caps	caps;
>  	struct xarray		qp_table_xa;
>  
> diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
> index 4c06889..0d26079 100644
> --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
> +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
> @@ -503,6 +503,8 @@ static inline int set_ud_wqe(struct hns_roce_qp *qp,
>  	if (ret)
>  		return ret;
>  
> +	qp->sl = to_hr_ah(ud_wr(wr)->ah)->av.sl;
> +
>  	set_extend_sge(qp, wr->sg_list, &curr_idx, valid_num_sge);
>  
>  	/*
> @@ -635,6 +637,8 @@ static inline void update_sq_db(struct hns_roce_dev *hr_dev,
>  			       V2_DB_BYTE_4_TAG_S, qp->doorbell_qpn);
>  		roce_set_field(sq_db.byte_4, V2_DB_BYTE_4_CMD_M,
>  			       V2_DB_BYTE_4_CMD_S, HNS_ROCE_V2_SQ_DB);
> +		/* indicates data on new BAR, 0 : SQ doorbell, 1 : DWQE */
> +		roce_set_bit(sq_db.byte_4, V2_DB_FLAG_S, 0);
>  		roce_set_field(sq_db.parameter, V2_DB_PARAMETER_IDX_M,
>  			       V2_DB_PARAMETER_IDX_S, qp->sq.head);
>  		roce_set_field(sq_db.parameter, V2_DB_PARAMETER_SL_M,
> @@ -644,6 +648,38 @@ static inline void update_sq_db(struct hns_roce_dev *hr_dev,
>  	}
>  }
>  
> +static void hns_roce_write512(struct hns_roce_dev *hr_dev, u64 *val,
> +			      u64 __iomem *dest)
> +{
> +#define HNS_ROCE_WRITE_TIMES 8
> +	struct hns_roce_v2_priv *priv = (struct hns_roce_v2_priv *)hr_dev->priv;
> +	struct hnae3_handle *handle = priv->handle;
> +	const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
> +	int i;
> +
> +	if (!hr_dev->dis_db && !ops->get_hw_reset_stat(handle))
> +		for (i = 0; i < HNS_ROCE_WRITE_TIMES; i++)
> +			writeq_relaxed(*(val + i), dest + i);
> +}
> +
> +static void write_dwqe(struct hns_roce_dev *hr_dev, struct hns_roce_qp *qp,
> +		       void *wqe)
> +{
> +	struct hns_roce_v2_rc_send_wqe *rc_sq_wqe = wqe;
> +
> +	/* All kinds of DirectWQE have the same header field layout */
> +	roce_set_bit(rc_sq_wqe->byte_4, V2_RC_SEND_WQE_BYTE_4_FLAG_S, 1);
> +	roce_set_field(rc_sq_wqe->byte_4, V2_RC_SEND_WQE_BYTE_4_DB_SL_L_M,
> +		       V2_RC_SEND_WQE_BYTE_4_DB_SL_L_S, qp->sl);
> +	roce_set_field(rc_sq_wqe->byte_4, V2_RC_SEND_WQE_BYTE_4_DB_SL_H_M,
> +		       V2_RC_SEND_WQE_BYTE_4_DB_SL_H_S, qp->sl >> 2);
> +	roce_set_field(rc_sq_wqe->byte_4, V2_RC_SEND_WQE_BYTE_4_WQE_INDEX_M,
> +		       V2_RC_SEND_WQE_BYTE_4_WQE_INDEX_S, qp->sq.head);
> +
> +	hns_roce_write512(hr_dev, wqe, hr_dev->mem_base +
> +			  HNS_ROCE_DWQE_SIZE * qp->ibqp.qp_num);
> +}
> +
>  static int hns_roce_v2_post_send(struct ib_qp *ibqp,
>  				 const struct ib_send_wr *wr,
>  				 const struct ib_send_wr **bad_wr)
> @@ -710,7 +746,12 @@ static int hns_roce_v2_post_send(struct ib_qp *ibqp,
>  		qp->next_sge = sge_idx;
>  		/* Memory barrier */
>  		wmb();
> -		update_sq_db(hr_dev, qp);
> +
> +		if (nreq == 1 && qp->sq.head == qp->sq.tail + 1 &&
> +		    (qp->en_flags & HNS_ROCE_QP_CAP_DIRECT_WQE))
> +			write_dwqe(hr_dev, qp, wqe);
> +		else
> +			update_sq_db(hr_dev, qp);
>  	}
>  
>  	spin_unlock_irqrestore(&qp->sq.lock, flags);
> @@ -6286,6 +6327,7 @@ static void hns_roce_hw_v2_get_cfg(struct hns_roce_dev *hr_dev,
>  
>  	/* Get info from NIC driver. */
>  	hr_dev->reg_base = handle->rinfo.roce_io_base;
> +	hr_dev->mem_base = handle->rinfo.roce_mem_base;
>  	hr_dev->caps.num_ports = 1;
>  	hr_dev->iboe.netdevs[0] = handle->rinfo.netdev;
>  	hr_dev->iboe.phy_port[0] = 0;
> diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
> index bdaccf8..badc1c9 100644
> --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
> +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
> @@ -97,6 +97,7 @@
>  #define HNS_ROCE_V2_PAGE_SIZE_SUPPORTED		0xFFFFF000
>  #define HNS_ROCE_V2_MAX_INNER_MTPT_NUM		2
>  #define HNS_ROCE_INVALID_LKEY			0x100
> +

Sorry, here is an extra blank line here, I will delete it and and send v2 later.

Weihang

>  #define HNS_ROCE_CMQ_TX_TIMEOUT			30000
>  #define HNS_ROCE_V2_UC_RC_SGE_NUM_IN_WQE	2
>  #define HNS_ROCE_V2_RSV_QPS			8
> @@ -1059,6 +1060,8 @@ struct hns_roce_v2_mpt_entry {
>  #define	V2_DB_BYTE_4_CMD_S 24
>  #define V2_DB_BYTE_4_CMD_M GENMASK(27, 24)
>  
> +#define V2_DB_FLAG_S 31
> +
>  #define V2_DB_PARAMETER_IDX_S 0
>  #define V2_DB_PARAMETER_IDX_M GENMASK(15, 0)
>  
> @@ -1155,6 +1158,15 @@ struct hns_roce_v2_rc_send_wqe {
>  #define	V2_RC_SEND_WQE_BYTE_4_OPCODE_S 0
>  #define V2_RC_SEND_WQE_BYTE_4_OPCODE_M GENMASK(4, 0)
>  
> +#define V2_RC_SEND_WQE_BYTE_4_DB_SL_L_S 5
> +#define V2_RC_SEND_WQE_BYTE_4_DB_SL_L_M GENMASK(6, 5)
> +
> +#define V2_RC_SEND_WQE_BYTE_4_DB_SL_H_S 13
> +#define V2_RC_SEND_WQE_BYTE_4_DB_SL_H_M GENMASK(14, 13)
> +
> +#define V2_RC_SEND_WQE_BYTE_4_WQE_INDEX_S 15
> +#define V2_RC_SEND_WQE_BYTE_4_WQE_INDEX_M GENMASK(30, 15)
> +
>  #define V2_RC_SEND_WQE_BYTE_4_OWNER_S 7
>  
>  #define V2_RC_SEND_WQE_BYTE_4_CQE_S 8
> @@ -1177,6 +1189,8 @@ struct hns_roce_v2_rc_send_wqe {
>  
>  #define V2_RC_FRMR_WQE_BYTE_4_LW_S 23
>  
> +#define V2_RC_SEND_WQE_BYTE_4_FLAG_S 31
> +
>  #define	V2_RC_SEND_WQE_BYTE_16_XRC_SRQN_S 0
>  #define V2_RC_SEND_WQE_BYTE_16_XRC_SRQN_M GENMASK(23, 0)
>  
>
diff mbox series

Patch

diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
index c46b330..6abf7d8 100644
--- a/drivers/infiniband/hw/hns/hns_roce_device.h
+++ b/drivers/infiniband/hw/hns/hns_roce_device.h
@@ -90,6 +90,7 @@ 
 #define HNS_ROCE_MAX_PORTS			6
 #define HNS_ROCE_GID_SIZE			16
 #define HNS_ROCE_SGE_SIZE			16
+#define HNS_ROCE_DWQE_SIZE			65536
 
 #define HNS_ROCE_HOP_NUM_0			0xff
 
@@ -644,6 +645,10 @@  struct hns_roce_work {
 	u32 queue_num;
 };
 
+enum {
+	HNS_ROCE_QP_CAP_DIRECT_WQE = BIT(5),
+};
+
 struct hns_roce_qp {
 	struct ib_qp		ibqp;
 	struct hns_roce_wq	rq;
@@ -986,6 +991,7 @@  struct hns_roce_dev {
 	struct mutex            pgdir_mutex;
 	int			irq[HNS_ROCE_MAX_IRQ_NUM];
 	u8 __iomem		*reg_base;
+	void __iomem		*mem_base;
 	struct hns_roce_caps	caps;
 	struct xarray		qp_table_xa;
 
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
index 4c06889..0d26079 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
@@ -503,6 +503,8 @@  static inline int set_ud_wqe(struct hns_roce_qp *qp,
 	if (ret)
 		return ret;
 
+	qp->sl = to_hr_ah(ud_wr(wr)->ah)->av.sl;
+
 	set_extend_sge(qp, wr->sg_list, &curr_idx, valid_num_sge);
 
 	/*
@@ -635,6 +637,8 @@  static inline void update_sq_db(struct hns_roce_dev *hr_dev,
 			       V2_DB_BYTE_4_TAG_S, qp->doorbell_qpn);
 		roce_set_field(sq_db.byte_4, V2_DB_BYTE_4_CMD_M,
 			       V2_DB_BYTE_4_CMD_S, HNS_ROCE_V2_SQ_DB);
+		/* indicates data on new BAR, 0 : SQ doorbell, 1 : DWQE */
+		roce_set_bit(sq_db.byte_4, V2_DB_FLAG_S, 0);
 		roce_set_field(sq_db.parameter, V2_DB_PARAMETER_IDX_M,
 			       V2_DB_PARAMETER_IDX_S, qp->sq.head);
 		roce_set_field(sq_db.parameter, V2_DB_PARAMETER_SL_M,
@@ -644,6 +648,38 @@  static inline void update_sq_db(struct hns_roce_dev *hr_dev,
 	}
 }
 
+static void hns_roce_write512(struct hns_roce_dev *hr_dev, u64 *val,
+			      u64 __iomem *dest)
+{
+#define HNS_ROCE_WRITE_TIMES 8
+	struct hns_roce_v2_priv *priv = (struct hns_roce_v2_priv *)hr_dev->priv;
+	struct hnae3_handle *handle = priv->handle;
+	const struct hnae3_ae_ops *ops = handle->ae_algo->ops;
+	int i;
+
+	if (!hr_dev->dis_db && !ops->get_hw_reset_stat(handle))
+		for (i = 0; i < HNS_ROCE_WRITE_TIMES; i++)
+			writeq_relaxed(*(val + i), dest + i);
+}
+
+static void write_dwqe(struct hns_roce_dev *hr_dev, struct hns_roce_qp *qp,
+		       void *wqe)
+{
+	struct hns_roce_v2_rc_send_wqe *rc_sq_wqe = wqe;
+
+	/* All kinds of DirectWQE have the same header field layout */
+	roce_set_bit(rc_sq_wqe->byte_4, V2_RC_SEND_WQE_BYTE_4_FLAG_S, 1);
+	roce_set_field(rc_sq_wqe->byte_4, V2_RC_SEND_WQE_BYTE_4_DB_SL_L_M,
+		       V2_RC_SEND_WQE_BYTE_4_DB_SL_L_S, qp->sl);
+	roce_set_field(rc_sq_wqe->byte_4, V2_RC_SEND_WQE_BYTE_4_DB_SL_H_M,
+		       V2_RC_SEND_WQE_BYTE_4_DB_SL_H_S, qp->sl >> 2);
+	roce_set_field(rc_sq_wqe->byte_4, V2_RC_SEND_WQE_BYTE_4_WQE_INDEX_M,
+		       V2_RC_SEND_WQE_BYTE_4_WQE_INDEX_S, qp->sq.head);
+
+	hns_roce_write512(hr_dev, wqe, hr_dev->mem_base +
+			  HNS_ROCE_DWQE_SIZE * qp->ibqp.qp_num);
+}
+
 static int hns_roce_v2_post_send(struct ib_qp *ibqp,
 				 const struct ib_send_wr *wr,
 				 const struct ib_send_wr **bad_wr)
@@ -710,7 +746,12 @@  static int hns_roce_v2_post_send(struct ib_qp *ibqp,
 		qp->next_sge = sge_idx;
 		/* Memory barrier */
 		wmb();
-		update_sq_db(hr_dev, qp);
+
+		if (nreq == 1 && qp->sq.head == qp->sq.tail + 1 &&
+		    (qp->en_flags & HNS_ROCE_QP_CAP_DIRECT_WQE))
+			write_dwqe(hr_dev, qp, wqe);
+		else
+			update_sq_db(hr_dev, qp);
 	}
 
 	spin_unlock_irqrestore(&qp->sq.lock, flags);
@@ -6286,6 +6327,7 @@  static void hns_roce_hw_v2_get_cfg(struct hns_roce_dev *hr_dev,
 
 	/* Get info from NIC driver. */
 	hr_dev->reg_base = handle->rinfo.roce_io_base;
+	hr_dev->mem_base = handle->rinfo.roce_mem_base;
 	hr_dev->caps.num_ports = 1;
 	hr_dev->iboe.netdevs[0] = handle->rinfo.netdev;
 	hr_dev->iboe.phy_port[0] = 0;
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
index bdaccf8..badc1c9 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
@@ -97,6 +97,7 @@ 
 #define HNS_ROCE_V2_PAGE_SIZE_SUPPORTED		0xFFFFF000
 #define HNS_ROCE_V2_MAX_INNER_MTPT_NUM		2
 #define HNS_ROCE_INVALID_LKEY			0x100
+
 #define HNS_ROCE_CMQ_TX_TIMEOUT			30000
 #define HNS_ROCE_V2_UC_RC_SGE_NUM_IN_WQE	2
 #define HNS_ROCE_V2_RSV_QPS			8
@@ -1059,6 +1060,8 @@  struct hns_roce_v2_mpt_entry {
 #define	V2_DB_BYTE_4_CMD_S 24
 #define V2_DB_BYTE_4_CMD_M GENMASK(27, 24)
 
+#define V2_DB_FLAG_S 31
+
 #define V2_DB_PARAMETER_IDX_S 0
 #define V2_DB_PARAMETER_IDX_M GENMASK(15, 0)
 
@@ -1155,6 +1158,15 @@  struct hns_roce_v2_rc_send_wqe {
 #define	V2_RC_SEND_WQE_BYTE_4_OPCODE_S 0
 #define V2_RC_SEND_WQE_BYTE_4_OPCODE_M GENMASK(4, 0)
 
+#define V2_RC_SEND_WQE_BYTE_4_DB_SL_L_S 5
+#define V2_RC_SEND_WQE_BYTE_4_DB_SL_L_M GENMASK(6, 5)
+
+#define V2_RC_SEND_WQE_BYTE_4_DB_SL_H_S 13
+#define V2_RC_SEND_WQE_BYTE_4_DB_SL_H_M GENMASK(14, 13)
+
+#define V2_RC_SEND_WQE_BYTE_4_WQE_INDEX_S 15
+#define V2_RC_SEND_WQE_BYTE_4_WQE_INDEX_M GENMASK(30, 15)
+
 #define V2_RC_SEND_WQE_BYTE_4_OWNER_S 7
 
 #define V2_RC_SEND_WQE_BYTE_4_CQE_S 8
@@ -1177,6 +1189,8 @@  struct hns_roce_v2_rc_send_wqe {
 
 #define V2_RC_FRMR_WQE_BYTE_4_LW_S 23
 
+#define V2_RC_SEND_WQE_BYTE_4_FLAG_S 31
+
 #define	V2_RC_SEND_WQE_BYTE_16_XRC_SRQN_S 0
 #define V2_RC_SEND_WQE_BYTE_16_XRC_SRQN_M GENMASK(23, 0)