OSDN Git Service

IB/hfi1: Add a function to build TID RDMA WRITE DATA packet
authorKaike Wan <kaike.wan@intel.com>
Thu, 24 Jan 2019 05:49:41 +0000 (21:49 -0800)
committerDoug Ledford <dledford@redhat.com>
Tue, 5 Feb 2019 23:07:43 +0000 (18:07 -0500)
This patch adds a function to build TID RDMA WRITE DATA packet.

Signed-off-by: Mitko Haralanov <mitko.haralanov@intel.com>
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Ashutosh Dixit <ashutosh.dixit@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/tid_rdma.c
drivers/infiniband/hw/hfi1/tid_rdma.h

index 92b6a3d..243fead 100644 (file)
@@ -3943,3 +3943,65 @@ ack_done:
        if (is_fecn)
                hfi1_send_rc_ack(packet, is_fecn);
 }
+
+bool hfi1_build_tid_rdma_packet(struct rvt_swqe *wqe,
+                               struct ib_other_headers *ohdr,
+                               u32 *bth1, u32 *bth2, u32 *len)
+{
+       struct tid_rdma_request *req = wqe_to_tid_req(wqe);
+       struct tid_rdma_flow *flow = &req->flows[req->clear_tail];
+       struct tid_rdma_params *remote;
+       struct rvt_qp *qp = req->qp;
+       struct hfi1_qp_priv *qpriv = qp->priv;
+       u32 tidentry = flow->tid_entry[flow->tid_idx];
+       u32 tidlen = EXP_TID_GET(tidentry, LEN) << PAGE_SHIFT;
+       struct tid_rdma_write_data *wd = &ohdr->u.tid_rdma.w_data;
+       u32 next_offset, om = KDETH_OM_LARGE;
+       bool last_pkt;
+
+       if (!tidlen) {
+               hfi1_trdma_send_complete(qp, wqe, IB_WC_REM_INV_RD_REQ_ERR);
+               rvt_error_qp(qp, IB_WC_REM_INV_RD_REQ_ERR);
+       }
+
+       *len = min_t(u32, qp->pmtu, tidlen - flow->tid_offset);
+       flow->sent += *len;
+       next_offset = flow->tid_offset + *len;
+       last_pkt = (flow->tid_idx == (flow->tidcnt - 1) &&
+                   next_offset >= tidlen) || (flow->sent >= flow->length);
+
+       rcu_read_lock();
+       remote = rcu_dereference(qpriv->tid_rdma.remote);
+       KDETH_RESET(wd->kdeth0, KVER, 0x1);
+       KDETH_SET(wd->kdeth0, SH, !last_pkt);
+       KDETH_SET(wd->kdeth0, INTR, !!(!last_pkt && remote->urg));
+       KDETH_SET(wd->kdeth0, TIDCTRL, EXP_TID_GET(tidentry, CTRL));
+       KDETH_SET(wd->kdeth0, TID, EXP_TID_GET(tidentry, IDX));
+       KDETH_SET(wd->kdeth0, OM, om == KDETH_OM_LARGE);
+       KDETH_SET(wd->kdeth0, OFFSET, flow->tid_offset / om);
+       KDETH_RESET(wd->kdeth1, JKEY, remote->jkey);
+       wd->verbs_qp = cpu_to_be32(qp->remote_qpn);
+       rcu_read_unlock();
+
+       *bth1 = flow->tid_qpn;
+       *bth2 = mask_psn(((flow->flow_state.spsn + flow->pkt++) &
+                        HFI1_KDETH_BTH_SEQ_MASK) |
+                        (flow->flow_state.generation <<
+                         HFI1_KDETH_BTH_SEQ_SHIFT));
+       if (last_pkt) {
+               /* PSNs are zero-based, so +1 to count number of packets */
+               if (flow->flow_state.lpsn + 1 +
+                   rvt_div_round_up_mtu(qp, req->seg_len) >
+                   MAX_TID_FLOW_PSN)
+                       req->state = TID_REQUEST_SYNC;
+               *bth2 |= IB_BTH_REQ_ACK;
+       }
+
+       if (next_offset >= tidlen) {
+               flow->tid_offset = 0;
+               flow->tid_idx++;
+       } else {
+               flow->tid_offset = next_offset;
+       }
+       return last_pkt;
+}
index 6f11fd5..f28c7ab 100644 (file)
@@ -275,4 +275,8 @@ void hfi1_del_tid_reap_timer(struct rvt_qp *qp);
 
 void hfi1_rc_rcv_tid_rdma_write_resp(struct hfi1_packet *packet);
 
+bool hfi1_build_tid_rdma_packet(struct rvt_swqe *wqe,
+                               struct ib_other_headers *ohdr,
+                               u32 *bth1, u32 *bth2, u32 *len);
+
 #endif /* HFI1_TID_RDMA_H */