]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
IB/hfi1: Enable TID RDMA READ protocol
authorKaike Wan <kaike.wan@intel.com>
Thu, 24 Jan 2019 03:32:30 +0000 (19:32 -0800)
committerDoug Ledford <dledford@redhat.com>
Tue, 5 Feb 2019 22:53:55 +0000 (17:53 -0500)
This patch enables TID RDMA READ protocol by converting a qualified
RDMA READ request into a TID RDMA READ request internally:
(1) The TID RDMA capability must be enabled;
(2) The request must start on a 4K page boundary and all receiving
 buffers must start on 4K page boundaries;
(3) The request length must be a multiple of 4K and must be larger or
equal to 256K. Each receiving buffer length must be a multiple of 4K.

Signed-off-by: Mitko Haralanov <mitko.haralanov@intel.com>
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Kaike Wan <kaike.wan@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/hfi1/qp.c
drivers/infiniband/hw/hfi1/tid_rdma.c
drivers/infiniband/hw/hfi1/tid_rdma.h

index 5fea7319167e8c9b4220a2a128eafdb363bc36fd..acdd9eba189b43ea5111daf5cc8480202d3bab5e 100644 (file)
@@ -319,6 +319,7 @@ int hfi1_setup_wqe(struct rvt_qp *qp, struct rvt_swqe *wqe, bool *call_send)
 
        switch (qp->ibqp.qp_type) {
        case IB_QPT_RC:
+               hfi1_setup_tid_rdma_wqe(qp, wqe);
        case IB_QPT_UC:
                if (wqe->length > 0x80000000U)
                        return -EINVAL;
index ccf15c9e76f85df107232d438881cac930618ca2..d65c030911c941ed4113ca7adae1921a15538097 100644 (file)
@@ -2866,3 +2866,71 @@ interlock:
        priv->s_flags |= HFI1_S_TID_WAIT_INTERLCK;
        return true;
 }
+
+/* Does @sge meet the alignment requirements for tid rdma? */
+static inline bool hfi1_check_sge_align(struct rvt_sge *sge, int num_sge)
+{
+       int i;
+
+       for (i = 0; i < num_sge; i++, sge++)
+               if ((u64)sge->vaddr & ~PAGE_MASK ||
+                   sge->sge_length & ~PAGE_MASK)
+                       return false;
+       return true;
+}
+
+void setup_tid_rdma_wqe(struct rvt_qp *qp, struct rvt_swqe *wqe)
+{
+       struct hfi1_qp_priv *qpriv = (struct hfi1_qp_priv *)qp->priv;
+       struct hfi1_swqe_priv *priv = wqe->priv;
+       struct tid_rdma_params *remote;
+       enum ib_wr_opcode new_opcode;
+       bool do_tid_rdma = false;
+       struct hfi1_pportdata *ppd = qpriv->rcd->ppd;
+
+       if ((rdma_ah_get_dlid(&qp->remote_ah_attr) & ~((1 << ppd->lmc) - 1)) ==
+                               ppd->lid)
+               return;
+       if (qpriv->hdr_type != HFI1_PKT_TYPE_9B)
+               return;
+
+       rcu_read_lock();
+       remote = rcu_dereference(qpriv->tid_rdma.remote);
+       /*
+        * If TID RDMA is disabled by the negotiation, don't
+        * use it.
+        */
+       if (!remote)
+               goto exit;
+
+       if (wqe->wr.opcode == IB_WR_RDMA_READ) {
+               if (hfi1_check_sge_align(&wqe->sg_list[0], wqe->wr.num_sge)) {
+                       new_opcode = IB_WR_TID_RDMA_READ;
+                       do_tid_rdma = true;
+               }
+       }
+
+       if (do_tid_rdma) {
+               if (hfi1_kern_exp_rcv_alloc_flows(&priv->tid_req, GFP_ATOMIC))
+                       goto exit;
+               wqe->wr.opcode = new_opcode;
+               priv->tid_req.seg_len =
+                       min_t(u32, remote->max_len, wqe->length);
+               priv->tid_req.total_segs =
+                       DIV_ROUND_UP(wqe->length, priv->tid_req.seg_len);
+               /* Compute the last PSN of the request */
+               wqe->lpsn = wqe->psn;
+               if (wqe->wr.opcode == IB_WR_TID_RDMA_READ) {
+                       priv->tid_req.n_flows = remote->max_read;
+                       qpriv->tid_r_reqs++;
+                       wqe->lpsn += rvt_div_round_up_mtu(qp, wqe->length) - 1;
+               }
+
+               priv->tid_req.cur_seg = 0;
+               priv->tid_req.comp_seg = 0;
+               priv->tid_req.ack_seg = 0;
+               priv->tid_req.state = TID_REQUEST_INACTIVE;
+       }
+exit:
+       rcu_read_unlock();
+}
index 689a5490432fdc5fe4798415a5765213bac91c94..a53598ce45b2d261d76c29ed3193c93e929152fe 100644 (file)
@@ -14,6 +14,7 @@
 #define CIRC_NEXT(val, size) CIRC_ADD(val, 1, size)
 #define CIRC_PREV(val, size) CIRC_ADD(val, -1, size)
 
+#define TID_RDMA_MIN_SEGMENT_SIZE       BIT(18)   /* 256 KiB (for now) */
 #define TID_RDMA_MAX_SEGMENT_SIZE       BIT(18)   /* 256 KiB (for now) */
 #define TID_RDMA_MAX_PAGES              (BIT(18) >> PAGE_SHIFT)
 
@@ -222,4 +223,14 @@ void hfi1_tid_rdma_restart_req(struct rvt_qp *qp, struct rvt_swqe *wqe,
 void hfi1_qp_kern_exp_rcv_clear_all(struct rvt_qp *qp);
 bool hfi1_tid_rdma_wqe_interlock(struct rvt_qp *qp, struct rvt_swqe *wqe);
 
+void setup_tid_rdma_wqe(struct rvt_qp *qp, struct rvt_swqe *wqe);
+static inline void hfi1_setup_tid_rdma_wqe(struct rvt_qp *qp,
+                                          struct rvt_swqe *wqe)
+{
+       if (wqe->priv &&
+           wqe->wr.opcode == IB_WR_RDMA_READ &&
+           wqe->length >= TID_RDMA_MIN_SEGMENT_SIZE)
+               setup_tid_rdma_wqe(qp, wqe);
+}
+
 #endif /* HFI1_TID_RDMA_H */