2006-12-04 16:02:08 +03:00
/*
* Unix SMB / CIFS implementation .
* Wrap Infiniband calls .
*
* Copyright ( C ) Sven Oehme < oehmes @ de . ibm . com > 2006
*
* Major code contributions by Peter Somogyi < psomogyi @ gamax . hu >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
2007-07-10 09:29:31 +04:00
* the Free Software Foundation ; either version 3 of the License , or
2006-12-04 16:02:08 +03:00
* ( at your option ) any later version .
*
* 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 .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
2006-12-13 13:02:49 +03:00
struct ibw_opts {
2006-12-20 19:42:58 +03:00
uint32_t max_send_wr ;
uint32_t max_recv_wr ;
uint32_t recv_bufsize ;
uint32_t recv_threshold ;
2006-12-13 13:02:49 +03:00
} ;
2006-12-04 16:02:08 +03:00
2006-12-13 13:02:49 +03:00
struct ibw_wr {
2007-02-08 21:06:14 +03:00
char * buf ; /* initialized in ibw_init_memory once per connection */
2006-12-11 21:56:15 +03:00
int wr_id ; /* position in wr_index list; also used as wr id */
2006-12-18 22:52:49 +03:00
2007-02-08 21:06:14 +03:00
char * buf_large ; /* allocated specially for "large" message */
2006-12-18 22:52:49 +03:00
struct ibv_mr * mr_large ;
2007-02-08 21:06:14 +03:00
int ref_cnt ; /* reference count for ibw_wc_send to know when to release */
2006-12-18 22:52:49 +03:00
2007-01-04 18:44:41 +03:00
char * queued_msg ; /* set at ibw_send - can be different than above */
2007-02-08 21:06:14 +03:00
int queued_ref_cnt ; /* instead of adding the same to the queue again */
uint32_t queued_rlen ; /* last wins when queued_ref_cnt>0; or simple msg size */
2007-01-04 18:44:41 +03:00
2006-12-13 17:00:41 +03:00
struct ibw_wr * next , * prev ; /* in wr_list_avail or wr_list_used */
2007-02-08 21:06:14 +03:00
/* or extra_sent or extra_avail */
struct ibw_wr * qnext , * qprev ; /* in queue */
2006-12-13 13:02:49 +03:00
} ;
2006-12-11 21:56:15 +03:00
2006-12-13 13:02:49 +03:00
struct ibw_ctx_priv {
2006-12-04 16:02:08 +03:00
struct event_context * ectx ;
2006-12-13 13:02:49 +03:00
struct ibw_opts opts ;
2006-12-04 16:02:08 +03:00
2006-12-04 21:48:11 +03:00
struct rdma_cm_id * cm_id ; /* server cm id */
2006-12-04 16:02:08 +03:00
struct rdma_event_channel * cm_channel ;
struct fd_event * cm_channel_event ;
2006-12-12 21:09:16 +03:00
ibw_connstate_fn_t connstate_func ; /* see ibw_init */
ibw_receive_fn_t receive_func ; /* see ibw_init */
2006-12-11 21:56:15 +03:00
long pagesize ; /* sysconf result for memalign */
2006-12-13 13:02:49 +03:00
} ;
2006-12-04 16:02:08 +03:00
2006-12-20 19:42:58 +03:00
struct ibw_part {
char * buf ; /* talloced memory buffer */
uint32_t bufsize ; /* allocated size of buf - always grows */
uint32_t len ; /* message part length */
uint32_t to_read ; /* 4 or *((uint32_t)buf) if len>=sizeof(uint32_t) */
2006-12-13 13:02:49 +03:00
} ;
2006-12-04 16:02:08 +03:00
2006-12-13 13:02:49 +03:00
struct ibw_conn_priv {
2006-12-12 21:09:16 +03:00
struct ibv_comp_channel * verbs_channel ;
struct fd_event * verbs_channel_event ;
2006-12-04 21:48:11 +03:00
struct rdma_cm_id * cm_id ; /* client's cm id */
2007-01-25 13:01:59 +03:00
struct ibv_pd * pd ;
2006-12-06 20:49:46 +03:00
int is_accepted ;
2006-12-04 16:02:08 +03:00
2006-12-11 21:56:15 +03:00
struct ibv_cq * cq ; /* qp is in cm_id */
2006-12-18 22:52:49 +03:00
char * buf_send ; /* max_send_wr * avg_send_size */
struct ibv_mr * mr_send ;
2006-12-13 13:02:49 +03:00
struct ibw_wr * wr_list_avail ;
struct ibw_wr * wr_list_used ;
struct ibw_wr * * wr_index ; /* array[0..(qsize-1)] of (ibw_wr *) */
2006-12-21 19:41:48 +03:00
int wr_sent ; /* # of send wrs in the CQ */
2006-12-18 22:52:49 +03:00
2006-12-21 19:41:48 +03:00
struct ibw_wr * extra_sent ;
struct ibw_wr * extra_avail ;
int extra_max ; /* max wr_id in the queue */
2006-12-20 21:16:30 +03:00
2007-02-08 21:06:14 +03:00
struct ibw_wr * queue ;
2006-12-18 22:52:49 +03:00
/* buf_recv is a ring buffer */
char * buf_recv ; /* max_recv_wr * avg_recv_size */
struct ibv_mr * mr_recv ;
2006-12-20 19:42:58 +03:00
int recv_index ; /* index of the next recv buffer when refilling */
struct ibw_part part ;
2006-12-13 13:02:49 +03:00
} ;
2006-12-04 16:02:08 +03:00
2007-02-08 21:06:14 +03:00
/* remove an element from a list - element doesn't have to be in list. */
# define DLIST_REMOVE2(list, p, prev, next) \
do { \
if ( ( p ) = = ( list ) ) { \
( list ) = ( p ) - > next ; \
if ( list ) ( list ) - > prev = NULL ; \
} else { \
if ( ( p ) - > prev ) ( p ) - > prev - > next = ( p ) - > next ; \
if ( ( p ) - > next ) ( p ) - > next - > prev = ( p ) - > prev ; \
} \
if ( ( p ) ! = ( list ) ) ( p ) - > next = ( p ) - > prev = NULL ; \
} while ( 0 )
/* hook into the end of the list - needs a tmp pointer */
# define DLIST_ADD_END2(list, p, type, prev, next) \
do { \
if ( ! ( list ) ) { \
( list ) = ( p ) ; \
( p ) - > next = ( p ) - > prev = NULL ; \
} else { \
type tmp ; \
for ( tmp = ( list ) ; tmp - > next ; tmp = tmp - > next ) ; \
tmp - > next = ( p ) ; \
( p ) - > next = NULL ; \
( p ) - > prev = tmp ; \
} \
} while ( 0 )