2016-01-06 20:50:24 +03:00
# ifndef DEF_RDMA_VT_H
# define DEF_RDMA_VT_H
/*
* Copyright ( c ) 2015 Intel Corporation .
*
* This file is provided under a dual BSD / GPLv2 license . When using or
* redistributing this file , you may do so under either license .
*
* GPL LICENSE SUMMARY
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* BSD LICENSE
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
*
* - Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* - Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in
* the documentation and / or other materials provided with the
* distribution .
* - Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
* SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT
* LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
*/
/*
* Structure that low level drivers will populate in order to register with the
* rdmavt layer .
*/
2016-01-06 21:04:13 +03:00
# include <linux/spinlock.h>
# include <linux/list.h>
2016-01-06 21:04:31 +03:00
# include <rdma/ib_verbs.h>
# include <rdma/rdmavt_mr.h>
# include <rdma/rdmavt_qp.h>
2016-01-06 21:03:47 +03:00
2016-01-06 21:03:07 +03:00
/*
* For some of the IBTA objects there will likely be some
* initializations required . We need flags to determine whether it is OK
* for rdmavt to do this or not . This does not imply any functions of a
* partiuclar IBTA object are overridden .
*/
# define RVT_FLAG_MR_INIT_DRIVER BIT(1)
# define RVT_FLAG_QP_INIT_DRIVER BIT(2)
# define RVT_FLAG_CQ_INIT_DRIVER BIT(3)
2016-01-06 21:05:12 +03:00
# define RVT_MAX_PKEY_VALUES 16
2016-01-06 21:04:13 +03:00
struct rvt_ibport {
struct rvt_qp __rcu * qp [ 2 ] ;
struct ib_mad_agent * send_agent ; /* agent for SMI (traps) */
struct rb_root mcast_tree ;
spinlock_t lock ; /* protect changes in this struct */
/* non-zero when timer is set */
unsigned long mkey_lease_timeout ;
unsigned long trap_timeout ;
__be64 gid_prefix ; /* in network order */
__be64 mkey ;
u64 tid ;
u32 port_cap_flags ;
u32 pma_sample_start ;
u32 pma_sample_interval ;
__be16 pma_counter_select [ 5 ] ;
u16 pma_tag ;
u16 mkey_lease_period ;
u16 sm_lid ;
u8 sm_sl ;
u8 mkeyprot ;
u8 subnet_timeout ;
u8 vl_high_limit ;
/*
* Driver is expected to keep these up to date . These
* counters are informational only and not required to be
* completely accurate .
*/
u64 n_rc_resends ;
u64 n_seq_naks ;
u64 n_rdma_seq ;
u64 n_rnr_naks ;
u64 n_other_naks ;
u64 n_loop_pkts ;
u64 n_pkt_drops ;
u64 n_vl15_dropped ;
u64 n_rc_timeouts ;
u64 n_dmawait ;
u64 n_unaligned ;
u64 n_rc_dupreq ;
u64 n_rc_seqnak ;
u16 pkey_violations ;
u16 qkey_violations ;
u16 mkey_violations ;
/* Hot-path per CPU counters to avoid cacheline trading to update */
u64 z_rc_acks ;
u64 z_rc_qacks ;
u64 z_rc_delayed_comp ;
u64 __percpu * rc_acks ;
u64 __percpu * rc_qacks ;
u64 __percpu * rc_delayed_comp ;
void * priv ; /* driver private data */
2016-01-06 21:05:12 +03:00
/*
* The pkey table is allocated and maintained by the driver . Drivers
* need to have access to this before registering with rdmav . However
* rdmavt will need access to it so drivers need to proviee this during
* the attach port API call .
*/
u16 * pkey_table ;
2016-01-06 21:04:13 +03:00
/* TODO: Move sm_ah and smi_ah into here as well*/
} ;
2016-01-06 20:51:48 +03:00
/*
* Things that are driver specific , module parameters in hfi1 and qib
*/
struct rvt_driver_params {
2016-01-06 20:52:19 +03:00
/*
* driver required fields :
* node_guid
* phys_port_cnt
* dma_device
* owner
* driver optional fields ( rvt will provide generic value if blank ) :
* name
* node_desc
* rvt fields , driver value ignored :
* uverbs_abi_ver
* node_type
* num_comp_vectors
* uverbs_cmd_mask
*/
struct ib_device_attr props ;
/*
* Drivers will need to support a number of notifications to rvt in
* accordance with certain events . This structure should contain a mask
* of the supported events . Such events that the rvt may need to know
* about include :
* port errors
* port active
* lid change
* sm change
* client reregister
* pkey change
*
* There may also be other events that the rvt layers needs to know
* about this is not an exhaustive list . Some events though rvt does not
* need to rely on the driver for such as completion queue error .
*/
int rvt_signal_supported ;
/*
* Anything driver specific that is not covered by props
* For instance special module parameters . Goes here .
*/
2016-01-06 21:03:31 +03:00
unsigned int lkey_table_size ;
2016-01-06 21:04:46 +03:00
unsigned int qp_table_size ;
int qpn_start ;
int qpn_inc ;
int qpn_res_start ;
int qpn_res_end ;
2016-01-06 21:04:13 +03:00
int nports ;
2016-01-06 21:05:12 +03:00
int npkeys ;
2016-01-06 21:04:46 +03:00
u8 qos_shift ;
2016-01-06 20:51:48 +03:00
} ;
2016-01-06 21:04:23 +03:00
/* Protection domain */
struct rvt_pd {
struct ib_pd ibpd ;
int user ; /* non-zero if created from user space */
} ;
/* Address handle */
struct rvt_ah {
struct ib_ah ibah ;
struct ib_ah_attr attr ;
atomic_t refcount ;
u8 vl ;
u8 log_pmtu ;
} ;
2016-01-06 21:02:59 +03:00
struct rvt_dev_info ;
2016-01-06 21:02:52 +03:00
struct rvt_driver_provided {
/*
* The work to create port files in / sys / class Infiniband is different
* depending on the driver . This should not be extracted away and
* instead drivers are responsible for setting the correct callback for
* this .
*/
2016-01-06 21:04:23 +03:00
/* -------------------*/
/* Required functions */
/* -------------------*/
2016-01-06 21:02:52 +03:00
int ( * port_callback ) ( struct ib_device * , u8 , struct kobject * ) ;
2016-01-06 21:02:59 +03:00
const char * ( * get_card_name ) ( struct rvt_dev_info * rdi ) ;
struct pci_dev * ( * get_pci_dev ) ( struct rvt_dev_info * rdi ) ;
2016-01-22 23:50:17 +03:00
unsigned ( * free_all_qps ) ( struct rvt_dev_info * rdi ) ;
void * ( * qp_priv_alloc ) ( struct rvt_dev_info * rdi , struct rvt_qp * qp ) ;
void ( * qp_priv_free ) ( struct rvt_dev_info * rdi , struct rvt_qp * qp ) ;
void ( * notify_qp_reset ) ( struct rvt_qp * qp ) ;
2016-01-06 21:02:52 +03:00
2016-01-06 21:04:23 +03:00
/*--------------------*/
/* Optional functions */
/*--------------------*/
int ( * check_ah ) ( struct ib_device * , struct ib_ah_attr * ) ;
void ( * notify_new_ah ) ( struct ib_device * , struct ib_ah_attr * ,
struct rvt_ah * ) ;
2016-01-22 23:50:17 +03:00
int ( * alloc_qpn ) ( struct rvt_dev_info * rdi , struct rvt_qpn_table * qpt ,
enum ib_qp_type type , u8 port ) ;
2016-01-06 21:03:59 +03:00
} ;
2016-01-06 20:50:24 +03:00
struct rvt_dev_info {
2016-01-06 21:03:31 +03:00
struct ib_device ibdev ; /* Keep this first. Nothing above here */
2016-01-06 20:52:19 +03:00
/*
* Prior to calling for registration the driver will be responsible for
* allocating space for this structure .
*
* The driver will also be responsible for filling in certain members of
* dparms . props
*/
2016-01-06 20:51:48 +03:00
2016-01-06 20:52:19 +03:00
/* Driver specific properties */
2016-01-06 20:51:48 +03:00
struct rvt_driver_params dparms ;
2016-01-06 20:52:19 +03:00
2016-01-06 21:01:42 +03:00
struct rvt_mregion __rcu * dma_mr ;
struct rvt_lkey_table lkey_table ;
2016-01-06 21:02:52 +03:00
/* Driver specific helper functions */
struct rvt_driver_provided driver_f ;
2016-01-06 20:50:24 +03:00
2016-01-06 20:51:48 +03:00
/* Internal use */
int n_pds_allocated ;
spinlock_t n_pds_lock ; /* Protect pd allocated count */
2016-01-06 21:03:07 +03:00
2016-01-06 21:03:59 +03:00
int n_ahs_allocated ;
spinlock_t n_ahs_lock ; /* Protect ah allocated count */
2016-01-06 21:03:07 +03:00
int flags ;
2016-01-06 21:04:13 +03:00
struct rvt_ibport * * ports ;
2016-01-06 21:04:46 +03:00
2016-01-22 23:50:17 +03:00
/* QP */
2016-01-06 21:04:46 +03:00
struct rvt_qp_ibdev * qp_dev ;
2016-01-22 23:50:17 +03:00
u32 n_qps_allocated ; /* number of QPs allocated for device */
spinlock_t n_qps_lock ; /* keep track of number of qps */
2016-01-06 21:04:57 +03:00
/* memory maps */
struct list_head pending_mmaps ;
spinlock_t mmap_offset_lock ; /* protect mmap_offset */
u32 mmap_offset ;
spinlock_t pending_lock ; /* protect pending mmap list */
2016-01-06 20:50:24 +03:00
} ;
2016-01-06 20:51:48 +03:00
static inline struct rvt_pd * ibpd_to_rvtpd ( struct ib_pd * ibpd )
{
return container_of ( ibpd , struct rvt_pd , ibpd ) ;
}
2016-01-06 21:03:59 +03:00
static inline struct rvt_ah * ibah_to_rvtah ( struct ib_ah * ibah )
{
return container_of ( ibah , struct rvt_ah , ibah ) ;
}
2016-01-06 20:51:48 +03:00
static inline struct rvt_dev_info * ib_to_rvt ( struct ib_device * ibdev )
{
return container_of ( ibdev , struct rvt_dev_info , ibdev ) ;
}
2016-01-06 21:04:06 +03:00
static inline struct rvt_srq * ibsrq_to_rvtsrq ( struct ib_srq * ibsrq )
{
return container_of ( ibsrq , struct rvt_srq , ibsrq ) ;
}
2016-01-06 21:05:12 +03:00
static inline unsigned rvt_get_npkeys ( struct rvt_dev_info * rdi )
{
/*
* All ports have same number of pkeys .
*/
return rdi - > dparms . npkeys ;
}
/*
* Return the indexed PKEY from the port PKEY table .
*/
static inline u16 rvt_get_pkey ( struct rvt_dev_info * rdi ,
int port_index ,
unsigned index )
{
if ( index > = rvt_get_npkeys ( rdi ) )
return 0 ;
else
return rdi - > ports [ port_index ] - > pkey_table [ index ] ;
}
2016-01-06 20:50:24 +03:00
int rvt_register_device ( struct rvt_dev_info * rvd ) ;
void rvt_unregister_device ( struct rvt_dev_info * rvd ) ;
2016-01-06 21:03:59 +03:00
int rvt_check_ah ( struct ib_device * ibdev , struct ib_ah_attr * ah_attr ) ;
2016-01-06 21:05:12 +03:00
int rvt_init_port ( struct rvt_dev_info * rdi , struct rvt_ibport * port ,
int portnum , u16 * pkey_table ) ;
2016-01-06 21:03:31 +03:00
int rvt_rkey_ok ( struct rvt_qp * qp , struct rvt_sge * sge ,
u32 len , u64 vaddr , u32 rkey , int acc ) ;
int rvt_lkey_ok ( struct rvt_lkey_table * rkt , struct rvt_pd * pd ,
struct rvt_sge * isge , struct ib_sge * sge , int acc ) ;
2016-01-06 21:04:57 +03:00
int rvt_mmap ( struct ib_ucontext * context , struct vm_area_struct * vma ) ;
void rvt_release_mmap_info ( struct kref * ref ) ;
struct rvt_mmap_info * rvt_create_mmap_info ( struct rvt_dev_info * rdi ,
u32 size ,
struct ib_ucontext * context ,
void * obj ) ;
void rvt_update_mmap_info ( struct rvt_dev_info * rdi , struct rvt_mmap_info * ip ,
u32 size , void * obj ) ;
2016-01-22 23:50:24 +03:00
/* Temporary export */
void rvt_reset_qp ( struct rvt_dev_info * rdi , struct rvt_qp * qp ,
enum ib_qp_type type ) ;
2016-01-06 20:50:24 +03:00
# endif /* DEF_RDMA_VT_H */