IB/hfi1: Add OPFN helper functions for TID RDMA feature
This patch adds the OPFN helper functions to initialize, encode, decode, and reset OPFN parameters for the TID RDMA feature. Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com> Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com> Signed-off-by: Mitko Haralanov <mitko.haralanov@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>
This commit is contained in:
@@ -8,6 +8,208 @@
|
||||
#include "verbs.h"
|
||||
#include "tid_rdma.h"
|
||||
|
||||
/*
|
||||
* J_KEY for kernel contexts when TID RDMA is used.
|
||||
* See generate_jkey() in hfi.h for more information.
|
||||
*/
|
||||
#define TID_RDMA_JKEY 32
|
||||
#define HFI1_KERNEL_MIN_JKEY HFI1_ADMIN_JKEY_RANGE
|
||||
#define HFI1_KERNEL_MAX_JKEY (2 * HFI1_ADMIN_JKEY_RANGE - 1)
|
||||
|
||||
#define TID_RDMA_MAX_READ_SEGS_PER_REQ 6
|
||||
#define TID_RDMA_MAX_WRITE_SEGS_PER_REQ 4
|
||||
|
||||
#define TID_OPFN_QP_CTXT_MASK 0xff
|
||||
#define TID_OPFN_QP_CTXT_SHIFT 56
|
||||
#define TID_OPFN_QP_KDETH_MASK 0xff
|
||||
#define TID_OPFN_QP_KDETH_SHIFT 48
|
||||
#define TID_OPFN_MAX_LEN_MASK 0x7ff
|
||||
#define TID_OPFN_MAX_LEN_SHIFT 37
|
||||
#define TID_OPFN_TIMEOUT_MASK 0x1f
|
||||
#define TID_OPFN_TIMEOUT_SHIFT 32
|
||||
#define TID_OPFN_RESERVED_MASK 0x3f
|
||||
#define TID_OPFN_RESERVED_SHIFT 26
|
||||
#define TID_OPFN_URG_MASK 0x1
|
||||
#define TID_OPFN_URG_SHIFT 25
|
||||
#define TID_OPFN_VER_MASK 0x7
|
||||
#define TID_OPFN_VER_SHIFT 22
|
||||
#define TID_OPFN_JKEY_MASK 0x3f
|
||||
#define TID_OPFN_JKEY_SHIFT 16
|
||||
#define TID_OPFN_MAX_READ_MASK 0x3f
|
||||
#define TID_OPFN_MAX_READ_SHIFT 10
|
||||
#define TID_OPFN_MAX_WRITE_MASK 0x3f
|
||||
#define TID_OPFN_MAX_WRITE_SHIFT 4
|
||||
|
||||
/*
|
||||
* OPFN TID layout
|
||||
*
|
||||
* 63 47 31 15
|
||||
* NNNNNNNNKKKKKKKK MMMMMMMMMMMTTTTT DDDDDDUVVVJJJJJJ RRRRRRWWWWWWCCCC
|
||||
* 3210987654321098 7654321098765432 1098765432109876 5432109876543210
|
||||
* N - the context Number
|
||||
* K - the Kdeth_qp
|
||||
* M - Max_len
|
||||
* T - Timeout
|
||||
* D - reserveD
|
||||
* V - version
|
||||
* U - Urg capable
|
||||
* J - Jkey
|
||||
* R - max_Read
|
||||
* W - max_Write
|
||||
* C - Capcode
|
||||
*/
|
||||
|
||||
static u64 tid_rdma_opfn_encode(struct tid_rdma_params *p)
|
||||
{
|
||||
return
|
||||
(((u64)p->qp & TID_OPFN_QP_CTXT_MASK) <<
|
||||
TID_OPFN_QP_CTXT_SHIFT) |
|
||||
((((u64)p->qp >> 16) & TID_OPFN_QP_KDETH_MASK) <<
|
||||
TID_OPFN_QP_KDETH_SHIFT) |
|
||||
(((u64)((p->max_len >> PAGE_SHIFT) - 1) &
|
||||
TID_OPFN_MAX_LEN_MASK) << TID_OPFN_MAX_LEN_SHIFT) |
|
||||
(((u64)p->timeout & TID_OPFN_TIMEOUT_MASK) <<
|
||||
TID_OPFN_TIMEOUT_SHIFT) |
|
||||
(((u64)p->urg & TID_OPFN_URG_MASK) << TID_OPFN_URG_SHIFT) |
|
||||
(((u64)p->jkey & TID_OPFN_JKEY_MASK) << TID_OPFN_JKEY_SHIFT) |
|
||||
(((u64)p->max_read & TID_OPFN_MAX_READ_MASK) <<
|
||||
TID_OPFN_MAX_READ_SHIFT) |
|
||||
(((u64)p->max_write & TID_OPFN_MAX_WRITE_MASK) <<
|
||||
TID_OPFN_MAX_WRITE_SHIFT);
|
||||
}
|
||||
|
||||
static void tid_rdma_opfn_decode(struct tid_rdma_params *p, u64 data)
|
||||
{
|
||||
p->max_len = (((data >> TID_OPFN_MAX_LEN_SHIFT) &
|
||||
TID_OPFN_MAX_LEN_MASK) + 1) << PAGE_SHIFT;
|
||||
p->jkey = (data >> TID_OPFN_JKEY_SHIFT) & TID_OPFN_JKEY_MASK;
|
||||
p->max_write = (data >> TID_OPFN_MAX_WRITE_SHIFT) &
|
||||
TID_OPFN_MAX_WRITE_MASK;
|
||||
p->max_read = (data >> TID_OPFN_MAX_READ_SHIFT) &
|
||||
TID_OPFN_MAX_READ_MASK;
|
||||
p->qp =
|
||||
((((data >> TID_OPFN_QP_KDETH_SHIFT) & TID_OPFN_QP_KDETH_MASK)
|
||||
<< 16) |
|
||||
((data >> TID_OPFN_QP_CTXT_SHIFT) & TID_OPFN_QP_CTXT_MASK));
|
||||
p->urg = (data >> TID_OPFN_URG_SHIFT) & TID_OPFN_URG_MASK;
|
||||
p->timeout = (data >> TID_OPFN_TIMEOUT_SHIFT) & TID_OPFN_TIMEOUT_MASK;
|
||||
}
|
||||
|
||||
void tid_rdma_opfn_init(struct rvt_qp *qp, struct tid_rdma_params *p)
|
||||
{
|
||||
struct hfi1_qp_priv *priv = qp->priv;
|
||||
|
||||
p->qp = (kdeth_qp << 16) | priv->rcd->ctxt;
|
||||
p->max_len = TID_RDMA_MAX_SEGMENT_SIZE;
|
||||
p->jkey = priv->rcd->jkey;
|
||||
p->max_read = TID_RDMA_MAX_READ_SEGS_PER_REQ;
|
||||
p->max_write = TID_RDMA_MAX_WRITE_SEGS_PER_REQ;
|
||||
p->timeout = qp->timeout;
|
||||
p->urg = is_urg_masked(priv->rcd);
|
||||
}
|
||||
|
||||
bool tid_rdma_conn_req(struct rvt_qp *qp, u64 *data)
|
||||
{
|
||||
struct hfi1_qp_priv *priv = qp->priv;
|
||||
|
||||
*data = tid_rdma_opfn_encode(&priv->tid_rdma.local);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tid_rdma_conn_reply(struct rvt_qp *qp, u64 data)
|
||||
{
|
||||
struct hfi1_qp_priv *priv = qp->priv;
|
||||
struct tid_rdma_params *remote, *old;
|
||||
bool ret = true;
|
||||
|
||||
old = rcu_dereference_protected(priv->tid_rdma.remote,
|
||||
lockdep_is_held(&priv->opfn.lock));
|
||||
data &= ~0xfULL;
|
||||
/*
|
||||
* If data passed in is zero, return true so as not to continue the
|
||||
* negotiation process
|
||||
*/
|
||||
if (!data || !HFI1_CAP_IS_KSET(TID_RDMA))
|
||||
goto null;
|
||||
/*
|
||||
* If kzalloc fails, return false. This will result in:
|
||||
* * at the requester a new OPFN request being generated to retry
|
||||
* the negotiation
|
||||
* * at the responder, 0 being returned to the requester so as to
|
||||
* disable TID RDMA at both the requester and the responder
|
||||
*/
|
||||
remote = kzalloc(sizeof(*remote), GFP_ATOMIC);
|
||||
if (!remote) {
|
||||
ret = false;
|
||||
goto null;
|
||||
}
|
||||
|
||||
tid_rdma_opfn_decode(remote, data);
|
||||
priv->tid_timer_timeout_jiffies =
|
||||
usecs_to_jiffies((((4096UL * (1UL << remote->timeout)) /
|
||||
1000UL) << 3) * 7);
|
||||
rcu_assign_pointer(priv->tid_rdma.remote, remote);
|
||||
/*
|
||||
* A TID RDMA READ request's segment size is not equal to
|
||||
* remote->max_len only when the request's data length is smaller
|
||||
* than remote->max_len. In that case, there will be only one segment.
|
||||
* Therefore, when priv->pkts_ps is used to calculate req->cur_seg
|
||||
* during retry, it will lead to req->cur_seg = 0, which is exactly
|
||||
* what is expected.
|
||||
*/
|
||||
priv->pkts_ps = (u16)rvt_div_mtu(qp, remote->max_len);
|
||||
priv->timeout_shift = ilog2(priv->pkts_ps - 1) + 1;
|
||||
goto free;
|
||||
null:
|
||||
RCU_INIT_POINTER(priv->tid_rdma.remote, NULL);
|
||||
priv->timeout_shift = 0;
|
||||
free:
|
||||
if (old)
|
||||
kfree_rcu(old, rcu_head);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool tid_rdma_conn_resp(struct rvt_qp *qp, u64 *data)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
ret = tid_rdma_conn_reply(qp, *data);
|
||||
*data = 0;
|
||||
/*
|
||||
* If tid_rdma_conn_reply() returns error, set *data as 0 to indicate
|
||||
* TID RDMA could not be enabled. This will result in TID RDMA being
|
||||
* disabled at the requester too.
|
||||
*/
|
||||
if (ret)
|
||||
(void)tid_rdma_conn_req(qp, data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void tid_rdma_conn_error(struct rvt_qp *qp)
|
||||
{
|
||||
struct hfi1_qp_priv *priv = qp->priv;
|
||||
struct tid_rdma_params *old;
|
||||
|
||||
old = rcu_dereference_protected(priv->tid_rdma.remote,
|
||||
lockdep_is_held(&priv->opfn.lock));
|
||||
RCU_INIT_POINTER(priv->tid_rdma.remote, NULL);
|
||||
if (old)
|
||||
kfree_rcu(old, rcu_head);
|
||||
}
|
||||
|
||||
/* This is called at context initialization time */
|
||||
int hfi1_kern_exp_rcv_init(struct hfi1_ctxtdata *rcd, int reinit)
|
||||
{
|
||||
if (reinit)
|
||||
return 0;
|
||||
|
||||
BUILD_BUG_ON(TID_RDMA_JKEY < HFI1_KERNEL_MIN_JKEY);
|
||||
BUILD_BUG_ON(TID_RDMA_JKEY > HFI1_KERNEL_MAX_JKEY);
|
||||
rcd->jkey = TID_RDMA_JKEY;
|
||||
hfi1_set_ctxt_jkey(rcd->dd, rcd, rcd->jkey);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* qp_to_rcd - determine the receive context used by a qp
|
||||
* @qp - the qp
|
||||
|
مرجع در شماره جدید
Block a user