2018-11-28 10:22:31 -08:00
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
/*
* Copyright ( c ) 2018 Intel Corporation .
*
*/
# include "hfi.h"
# include "verbs.h"
# include "tid_rdma.h"
2019-01-23 19:20:42 -08:00
/*
* 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 ;
}
2018-11-28 10:22:31 -08:00
/**
* qp_to_rcd - determine the receive context used by a qp
* @ qp - the qp
*
* This routine returns the receive context associated
* with a a qp ' s qpn .
*
* Returns the context .
*/
static struct hfi1_ctxtdata * qp_to_rcd ( struct rvt_dev_info * rdi ,
struct rvt_qp * qp )
{
struct hfi1_ibdev * verbs_dev = container_of ( rdi ,
struct hfi1_ibdev ,
rdi ) ;
struct hfi1_devdata * dd = container_of ( verbs_dev ,
struct hfi1_devdata ,
verbs_dev ) ;
unsigned int ctxt ;
if ( qp - > ibqp . qp_num = = 0 )
ctxt = 0 ;
else
ctxt = ( ( qp - > ibqp . qp_num > > dd - > qos_shift ) %
( dd - > n_krcv_queues - 1 ) ) + 1 ;
return dd - > rcd [ ctxt ] ;
}
int hfi1_qp_priv_init ( struct rvt_dev_info * rdi , struct rvt_qp * qp ,
struct ib_qp_init_attr * init_attr )
{
struct hfi1_qp_priv * qpriv = qp - > priv ;
qpriv - > rcd = qp_to_rcd ( rdi , qp ) ;
2019-01-23 19:21:11 -08:00
spin_lock_init ( & qpriv - > opfn . lock ) ;
INIT_WORK ( & qpriv - > opfn . opfn_work , opfn_send_conn_request ) ;
2018-11-28 10:22:31 -08:00
return 0 ;
}
2019-01-23 19:21:11 -08:00
void hfi1_qp_priv_tid_free ( struct rvt_dev_info * rdi , struct rvt_qp * qp )
{
struct hfi1_qp_priv * priv = qp - > priv ;
if ( qp - > ibqp . qp_type = = IB_QPT_RC & & HFI1_CAP_IS_KSET ( TID_RDMA ) )
cancel_work_sync ( & priv - > opfn . opfn_work ) ;
}