Started added poll_cq() verb.
Started reworking MLX_EXTRACT(), MLX_POPULATE() etc. to automatically determine type information.
This commit is contained in:
parent
37a036bd48
commit
a3a91fedc1
|
@ -137,112 +137,139 @@ struct addr_64_st {
|
||||||
|
|
||||||
/* Remaining code Copyright Fen Systems Ltd. 2007 */
|
/* Remaining code Copyright Fen Systems Ltd. 2007 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper structure for pseudo_bit_t structures
|
||||||
|
*
|
||||||
|
* This structure provides a wrapper around the autogenerated
|
||||||
|
* pseudo_bit_t structures. It has the correct size, and also
|
||||||
|
* encapsulates type information about the underlying pseudo_bit_t
|
||||||
|
* structure, which allows the MLX_POPULATE etc. macros to work
|
||||||
|
* without requiring explicit type information.
|
||||||
|
*/
|
||||||
|
#define MLX_DECLARE_STRUCT( _structure ) \
|
||||||
|
_structure { \
|
||||||
|
union { \
|
||||||
|
uint8_t bytes[ sizeof ( struct _structure ## _st ) / 8 ]; \
|
||||||
|
uint32_t dwords[ sizeof ( struct _structure ## _st ) / 32 ]; \
|
||||||
|
struct _structure ## _st *dummy[0]; \
|
||||||
|
} u; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get pseudo_bit_t structure type from wrapper structure pointer */
|
||||||
|
#define MLX_PSEUDO_STRUCT( _ptr ) \
|
||||||
|
typeof ( *((_ptr)->u.dummy[0]) )
|
||||||
|
|
||||||
/** Bit offset of a field within a pseudo_bit_t structure */
|
/** Bit offset of a field within a pseudo_bit_t structure */
|
||||||
#define MLX_BIT_OFFSET( _structure, _field ) \
|
#define MLX_BIT_OFFSET( _structure_st, _field ) \
|
||||||
offsetof ( struct _structure, _field )
|
offsetof ( _structure_st, _field )
|
||||||
|
|
||||||
/** Dword offset of a field within a pseudo_bit_t structure */
|
/** Dword offset of a field within a pseudo_bit_t structure */
|
||||||
#define MLX_DWORD_OFFSET( _structure, _field ) \
|
#define MLX_DWORD_OFFSET( _structure_st, _field ) \
|
||||||
( MLX_BIT_OFFSET ( _structure, _field ) / 32 )
|
( MLX_BIT_OFFSET ( _structure_st, _field ) / 32 )
|
||||||
|
|
||||||
/** Dword bit offset of a field within a pseudo_bit_t structure
|
/** Dword bit offset of a field within a pseudo_bit_t structure
|
||||||
*
|
*
|
||||||
* Yes, using mod-32 would work, but would lose the check for the
|
* Yes, using mod-32 would work, but would lose the check for the
|
||||||
* error of specifying a mismatched field name and dword index.
|
* error of specifying a mismatched field name and dword index.
|
||||||
*/
|
*/
|
||||||
#define MLX_DWORD_BIT_OFFSET( _structure, _index, _field ) \
|
#define MLX_DWORD_BIT_OFFSET( _structure_st, _index, _field ) \
|
||||||
( MLX_BIT_OFFSET ( _structure, _field ) - ( 32 * (_index) ) )
|
( MLX_BIT_OFFSET ( _structure_st, _field ) - ( 32 * (_index) ) )
|
||||||
|
|
||||||
/** Bit width of a field within a pseudo_bit_t structure */
|
/** Bit width of a field within a pseudo_bit_t structure */
|
||||||
#define MLX_BIT_WIDTH( _structure, _field ) \
|
#define MLX_BIT_WIDTH( _structure_st, _field ) \
|
||||||
sizeof ( ( ( struct _structure * ) NULL )->_field )
|
sizeof ( ( ( _structure_st * ) NULL )->_field )
|
||||||
|
|
||||||
/** Bit mask for a field within a pseudo_bit_t structure */
|
/** Bit mask for a field within a pseudo_bit_t structure */
|
||||||
#define MLX_BIT_MASK( _structure, _field ) \
|
#define MLX_BIT_MASK( _structure_st, _field ) \
|
||||||
( ( 1 << MLX_BIT_WIDTH ( _structure, _field ) ) - 1 )
|
( ( 1 << MLX_BIT_WIDTH ( _structure_st, _field ) ) - 1 )
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Assemble native-endian dword from named fields and values
|
* Assemble native-endian dword from named fields and values
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MLX_ASSEMBLE_1( _structure, _index, _field, _value ) \
|
#define MLX_ASSEMBLE_1( _structure_st, _index, _field, _value ) \
|
||||||
( (_value) << MLX_DWORD_BIT_OFFSET ( _structure, _index, _field ) )
|
( (_value) << MLX_DWORD_BIT_OFFSET ( _structure_st, _index, _field ) )
|
||||||
|
|
||||||
#define MLX_ASSEMBLE_2( _structure, _index, _field, _value, ... ) \
|
#define MLX_ASSEMBLE_2( _structure_st, _index, _field, _value, ... ) \
|
||||||
( MLX_ASSEMBLE_1 ( _structure, _index, _field, _value ) | \
|
( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) | \
|
||||||
MLX_ASSEMBLE_1 ( _structure, _index, __VA_ARGS__ ) )
|
MLX_ASSEMBLE_1 ( _structure_st, _index, __VA_ARGS__ ) )
|
||||||
|
|
||||||
#define MLX_ASSEMBLE_3( _structure, _index, _field, _value, ... ) \
|
#define MLX_ASSEMBLE_3( _structure_st, _index, _field, _value, ... ) \
|
||||||
( MLX_ASSEMBLE_1 ( _structure, _index, _field, _value ) | \
|
( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) | \
|
||||||
MLX_ASSEMBLE_2 ( _structure, _index, __VA_ARGS__ ) )
|
MLX_ASSEMBLE_2 ( _structure_st, _index, __VA_ARGS__ ) )
|
||||||
|
|
||||||
#define MLX_ASSEMBLE_4( _structure, _index, _field, _value, ... ) \
|
#define MLX_ASSEMBLE_4( _structure_st, _index, _field, _value, ... ) \
|
||||||
( MLX_ASSEMBLE_1 ( _structure, _index, _field, _value ) | \
|
( MLX_ASSEMBLE_1 ( _structure_st, _index, _field, _value ) | \
|
||||||
MLX_ASSEMBLE_3 ( _structure, _index, __VA_ARGS__ ) )
|
MLX_ASSEMBLE_3 ( _structure_st, _index, __VA_ARGS__ ) )
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build native-endian (positive) dword bitmasks from named fields
|
* Build native-endian (positive) dword bitmasks from named fields
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MLX_MASK_1( _structure, _index, _field ) \
|
#define MLX_MASK_1( _structure_st, _index, _field ) \
|
||||||
( MLX_BIT_MASK ( _structure, _field ) << \
|
( MLX_BIT_MASK ( _structure_st, _field ) << \
|
||||||
MLX_DWORD_BIT_OFFSET ( _structure, _index, _field ) )
|
MLX_DWORD_BIT_OFFSET ( _structure_st, _index, _field ) )
|
||||||
|
|
||||||
#define MLX_MASK_2( _structure, _index, _field, ... ) \
|
#define MLX_MASK_2( _structure_st, _index, _field, ... ) \
|
||||||
( MLX_MASK_1 ( _structure, _index, _field ) | \
|
( MLX_MASK_1 ( _structure_st, _index, _field ) | \
|
||||||
MLX_MASK_1 ( _structure, _index, __VA_ARGS__ ) )
|
MLX_MASK_1 ( _structure_st, _index, __VA_ARGS__ ) )
|
||||||
|
|
||||||
#define MLX_MASK_3( _structure, _index, _field, ... ) \
|
#define MLX_MASK_3( _structure_st, _index, _field, ... ) \
|
||||||
( MLX_MASK_1 ( _structure, _index, _field ) | \
|
( MLX_MASK_1 ( _structure_st, _index, _field ) | \
|
||||||
MLX_MASK_2 ( _structure, _index, __VA_ARGS__ ) )
|
MLX_MASK_2 ( _structure_st, _index, __VA_ARGS__ ) )
|
||||||
|
|
||||||
#define MLX_MASK_4( _structure, _index, _field, ... ) \
|
#define MLX_MASK_4( _structure_st, _index, _field, ... ) \
|
||||||
( MLX_MASK_1 ( _structure, _index, _field ) | \
|
( MLX_MASK_1 ( _structure_st, _index, _field ) | \
|
||||||
MLX_MASK_3 ( _structure, _index, __VA_ARGS__ ) )
|
MLX_MASK_3 ( _structure_st, _index, __VA_ARGS__ ) )
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Populate big-endian dwords from named fields and values
|
* Populate big-endian dwords from named fields and values
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MLX_POPULATE( _base, _index, _assembled ) \
|
#define MLX_POPULATE( _ptr, _index, _assembled ) \
|
||||||
do { \
|
do { \
|
||||||
uint32_t *__ptr = ( ( (uint32_t *) (_base) ) + (_index) ); \
|
uint32_t *__ptr = &(_ptr)->u.dwords[(_index)]; \
|
||||||
uint32_t __assembled = (_assembled); \
|
uint32_t __assembled = (_assembled); \
|
||||||
*__ptr = cpu_to_be32 ( __assembled ); \
|
*__ptr = cpu_to_be32 ( __assembled ); \
|
||||||
} while ( 0 )
|
} while ( 0 )
|
||||||
|
|
||||||
#define MLX_POPULATE_1( _base, _structure, _index, ... ) \
|
#define MLX_POPULATE_1( _ptr, _index, ... ) \
|
||||||
MLX_POPULATE ( _base, _index, \
|
MLX_POPULATE ( _ptr, _index, \
|
||||||
MLX_ASSEMBLE_1 ( _structure, _index, __VA_ARGS__ ) )
|
MLX_ASSEMBLE_1 ( MLX_PSEUDO_STRUCT ( _ptr ), \
|
||||||
|
_index, __VA_ARGS__ ) )
|
||||||
|
|
||||||
#define MLX_POPULATE_2( _base, _structure, _index, ... ) \
|
#define MLX_POPULATE_2( _ptr, _index, ... ) \
|
||||||
MLX_POPULATE ( _base, _index, \
|
MLX_POPULATE ( _ptr, _index, \
|
||||||
MLX_ASSEMBLE_2 ( _structure, _index, __VA_ARGS__ ) )
|
MLX_ASSEMBLE_2 ( MLX_PSEUDO_STRUCT ( _ptr ), \
|
||||||
|
_index, __VA_ARGS__ ) )
|
||||||
|
|
||||||
#define MLX_POPULATE_3( _base, _structure, _index, ... ) \
|
#define MLX_POPULATE_3( _ptr, _index, ... ) \
|
||||||
MLX_POPULATE ( _base, _index, \
|
MLX_POPULATE ( _ptr, _index, \
|
||||||
MLX_ASSEMBLE_3 ( _structure, _index, __VA_ARGS__ ) )
|
MLX_ASSEMBLE_3 ( MLX_PSEUDO_STRUCT ( _ptr ), \
|
||||||
|
_index, __VA_ARGS__ ) )
|
||||||
|
|
||||||
#define MLX_POPULATE_4( _base, _structure, _index, ... ) \
|
#define MLX_POPULATE_4( _ptr, _index, ... ) \
|
||||||
MLX_POPULATE ( _base, _index, \
|
MLX_POPULATE ( _ptr, _index, \
|
||||||
MLX_ASSEMBLE_4 ( _structure, _index, __VA_ARGS__ ) )
|
MLX_ASSEMBLE_4 ( MLX_PSEUDO_STRUCT ( _ptr ), \
|
||||||
|
_index, __VA_ARGS__ ) )
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Modify big-endian dword using named field and value
|
* Modify big-endian dword using named field and value
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MLX_MODIFY( _base, _structure, _index, _field, _value ) \
|
#define MLX_MODIFY( _ptr, _index, _field, _value ) \
|
||||||
do { \
|
do { \
|
||||||
uint32_t *__ptr = ( ( (uint32_t *) (_base) ) + (_index) ); \
|
uint32_t *__ptr = &(_ptr)->u.dwords[(_index)]; \
|
||||||
uint32_t __value = be32_to_cpu ( *__ptr ); \
|
uint32_t __value = be32_to_cpu ( *__ptr ); \
|
||||||
__value &= ~( MLX_MASK_1 ( _structure, _index, _field ) ); \
|
__value &= ~( MLX_MASK_1 ( MLX_PSEUDO_STRUCT ( _ptr ), \
|
||||||
__value |= MLX_ASSEMBLE_1 ( _structure, _index, \
|
_index, _field ) ); \
|
||||||
_field, _value ); \
|
__value |= MLX_ASSEMBLE_1 ( MLX_PSEUDO_STRUCT ( _ptr ), \
|
||||||
*__ptr = cpu_to_be32 ( __value ); \
|
_index, _field, _value ); \
|
||||||
|
*__ptr = cpu_to_be32 ( __value ); \
|
||||||
} while ( 0 )
|
} while ( 0 )
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -250,16 +277,18 @@ struct addr_64_st {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MLX_EXTRACT( _base, _structure, _field ) \
|
#define MLX_EXTRACT( _ptr, _field ) \
|
||||||
( { \
|
( { \
|
||||||
unsigned int __index = \
|
unsigned int __index = \
|
||||||
MLX_DWORD_OFFSET ( _structure, _field ); \
|
MLX_DWORD_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ), _field ); \
|
||||||
uint32_t *__ptr = ( ( (uint32_t *) (_base) ) + __index ); \
|
uint32_t *__ptr = &(_ptr)->u.dwords[__index]; \
|
||||||
uint32_t __value = be32_to_cpu ( *__ptr ); \
|
uint32_t __value = be32_to_cpu ( *__ptr ); \
|
||||||
__value >>= MLX_DWORD_BIT_OFFSET ( _structure, __index, \
|
__value >>= \
|
||||||
_field ); \
|
MLX_DWORD_BIT_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ), \
|
||||||
__value &= MLX_BIT_MASK ( _structure, _field ); \
|
__index, _field ); \
|
||||||
__value; \
|
__value &= \
|
||||||
|
MLX_BIT_MASK ( MLX_PSEUDO_STRUCT ( _ptr ), _field ); \
|
||||||
|
__value; \
|
||||||
} )
|
} )
|
||||||
|
|
||||||
#endif /* __bit_ops_h__ */
|
#endif /* __bit_ops_h__ */
|
||||||
|
|
|
@ -23,14 +23,23 @@ Skeleton NIC driver for Etherboot
|
||||||
|
|
||||||
#include "mt25218_imp.c"
|
#include "mt25218_imp.c"
|
||||||
|
|
||||||
|
#include "arbel.h"
|
||||||
|
|
||||||
struct arbel_send_work_queue {
|
struct arbel_send_work_queue {
|
||||||
/** Doorbell number */
|
/** Doorbell record number */
|
||||||
unsigned int doorbell_idx;
|
unsigned int doorbell_idx;
|
||||||
/** Work queue entries */
|
/** Work queue entries */
|
||||||
// struct ud_send_wqe_st *wqe;
|
// struct ud_send_wqe_st *wqe;
|
||||||
union ud_send_wqe_u *wqe_u;
|
union ud_send_wqe_u *wqe_u;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct arbel_completion_queue {
|
||||||
|
/** Doorbell record number */
|
||||||
|
unsigned int doorbell_idx;
|
||||||
|
/** Completion queue entries */
|
||||||
|
union cqe_st *cqe;
|
||||||
|
};
|
||||||
|
|
||||||
struct arbel {
|
struct arbel {
|
||||||
/** User Access Region */
|
/** User Access Region */
|
||||||
void *uar;
|
void *uar;
|
||||||
|
@ -143,13 +152,14 @@ static int mlx_transmit_direct ( struct net_device *netdev,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
struct ud_av_st *bcast_av = mlx->bcast_av;
|
struct ud_av_st *bcast_av = mlx->bcast_av;
|
||||||
struct address_vector_st *bav = &bcast_av->av;
|
struct arbelprm_ud_address_vector *bav =
|
||||||
|
( struct arbelprm_ud_address_vector * ) &bcast_av->av;
|
||||||
struct ib_address_vector av = {
|
struct ib_address_vector av = {
|
||||||
.dest_qp = bcast_av->dest_qp,
|
.dest_qp = bcast_av->dest_qp,
|
||||||
.qkey = bcast_av->qkey,
|
.qkey = bcast_av->qkey,
|
||||||
.dlid = MLX_EXTRACT ( bav, arbelprm_ud_address_vector_st, rlid ),
|
.dlid = MLX_EXTRACT ( bav, rlid ),
|
||||||
.rate = ( MLX_EXTRACT ( bav, arbelprm_ud_address_vector_st, max_stat_rate ) ? 1 : 4 ),
|
.rate = ( MLX_EXTRACT ( bav, max_stat_rate ) ? 1 : 4 ),
|
||||||
.sl = MLX_EXTRACT ( bav, arbelprm_ud_address_vector_st, sl ),
|
.sl = MLX_EXTRACT ( bav, sl ),
|
||||||
.gid_present = 1,
|
.gid_present = 1,
|
||||||
};
|
};
|
||||||
memcpy ( &av.gid, ( ( void * ) bav ) + 16, 16 );
|
memcpy ( &av.gid, ( ( void * ) bav ) + 16, 16 );
|
||||||
|
@ -301,6 +311,13 @@ static struct ib_gid arbel_no_gid = {
|
||||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ring doorbell register in UAR
|
||||||
|
*
|
||||||
|
* @v arbel Arbel device
|
||||||
|
* @v db_reg Doorbell register structure
|
||||||
|
* @v offset Address of doorbell
|
||||||
|
*/
|
||||||
static void arbel_ring_doorbell ( struct arbel *arbel, void *db_reg,
|
static void arbel_ring_doorbell ( struct arbel *arbel, void *db_reg,
|
||||||
unsigned int offset ) {
|
unsigned int offset ) {
|
||||||
uint32_t *db_reg_dword = db_reg;
|
uint32_t *db_reg_dword = db_reg;
|
||||||
|
@ -315,6 +332,15 @@ static void arbel_ring_doorbell ( struct arbel *arbel, void *db_reg,
|
||||||
writel ( db_reg_dword[1], ( arbel->uar + offset + 4 ) );
|
writel ( db_reg_dword[1], ( arbel->uar + offset + 4 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post send work queue entry
|
||||||
|
*
|
||||||
|
* @v ibdev Infiniband device
|
||||||
|
* @v iobuf I/O buffer
|
||||||
|
* @v av Address vector
|
||||||
|
* @v qp Queue pair
|
||||||
|
* @ret rc Return status code
|
||||||
|
*/
|
||||||
static int arbel_post_send ( struct ib_device *ibdev, struct io_buffer *iobuf,
|
static int arbel_post_send ( struct ib_device *ibdev, struct io_buffer *iobuf,
|
||||||
struct ib_address_vector *av,
|
struct ib_address_vector *av,
|
||||||
struct ib_queue_pair *qp ) {
|
struct ib_queue_pair *qp ) {
|
||||||
|
@ -365,14 +391,8 @@ static int arbel_post_send ( struct ib_device *ibdev, struct io_buffer *iobuf,
|
||||||
destination_qp, av->dest_qp );
|
destination_qp, av->dest_qp );
|
||||||
MLX_POPULATE_1 ( &wqe->udseg, arbelprm_wqe_segment_ud_st, 9,
|
MLX_POPULATE_1 ( &wqe->udseg, arbelprm_wqe_segment_ud_st, 9,
|
||||||
q_key, av->qkey );
|
q_key, av->qkey );
|
||||||
|
|
||||||
wqe->mpointer[0].local_addr_l =
|
wqe->mpointer[0].local_addr_l =
|
||||||
cpu_to_be32 ( virt_to_bus ( iobuf->data ) );
|
cpu_to_be32 ( virt_to_bus ( iobuf->data ) );
|
||||||
|
|
||||||
// memcpy ( bus_to_virt ( be32_to_cpu ( wqe->mpointer[0].local_addr_l ) ),
|
|
||||||
// iobuf->data, iob_len ( iobuf ) );
|
|
||||||
|
|
||||||
|
|
||||||
wqe->mpointer[0].byte_count = cpu_to_be32 ( iob_len ( iobuf ) );
|
wqe->mpointer[0].byte_count = cpu_to_be32 ( iob_len ( iobuf ) );
|
||||||
|
|
||||||
DBG ( "Work queue entry:\n" );
|
DBG ( "Work queue entry:\n" );
|
||||||
|
@ -416,8 +436,69 @@ static int arbel_post_send ( struct ib_device *ibdev, struct io_buffer *iobuf,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void arbel_parse_completion ( struct arbel *arbel,
|
||||||
|
union cqe_st *cqe,
|
||||||
|
struct ib_completion *completion ) {
|
||||||
|
memset ( completion, 0, sizeof ( *completion ) );
|
||||||
|
is_send = MLX_EXTRACT ( cqe, arbelprm_completion_queue_entry_st, s );
|
||||||
|
completion->len =
|
||||||
|
MLX_EXTRACT ( cqe, arbelprm_completion_queue_entry_st,
|
||||||
|
byte_cnt );}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Poll completion queue
|
||||||
|
*
|
||||||
|
* @v ibdev Infiniband device
|
||||||
|
* @v cq Completion queue
|
||||||
|
* @v complete Completion handler
|
||||||
|
*/
|
||||||
|
static void arbel_poll_cq ( struct ib_device *ibdev,
|
||||||
|
struct ib_completion_queue *cq,
|
||||||
|
ib_completer_t complete_send,
|
||||||
|
ib_completer_t complete_recv ) {
|
||||||
|
struct arbel *arbel = ibdev->priv;
|
||||||
|
struct arbel_completion_queue *arbel_cq = cq->priv;
|
||||||
|
unsigned int cqe_idx_mask = ( cq->num_cqes - 1 );
|
||||||
|
union db_record_st *db_rec = &arbel->db_rec[arbel_cq->doorbell_idx];
|
||||||
|
union cqe_st *cqe;
|
||||||
|
struct ib_completion completion;
|
||||||
|
struct io_buffer *iobuf;
|
||||||
|
int is_send;
|
||||||
|
|
||||||
|
while ( 1 ) {
|
||||||
|
/* Look for completion entry */
|
||||||
|
cqe = &arbel_cq->cqe[cq->next_idx & cqe_idx_mask];
|
||||||
|
if ( MLX_EXTRACT ( cqe, arbelprm_completion_queue_entry_st,
|
||||||
|
owner ) != 0 ) {
|
||||||
|
/* Entry still owned by hardware; end of poll */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse completion */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Handle completion */
|
||||||
|
( is_send ? complete_send : complete_recv ) ( ibdev,
|
||||||
|
&completion,
|
||||||
|
iobuf );
|
||||||
|
|
||||||
|
/* Return ownership to hardware */
|
||||||
|
MLX_POPULATE_1 ( cqe, arbelprm_completion_queue_entry_st, 7,
|
||||||
|
owner, 1 );
|
||||||
|
barrier();
|
||||||
|
/* Update completion queue's index */
|
||||||
|
cq->next_idx++;
|
||||||
|
/* Update doorbell record */
|
||||||
|
MLX_POPULATE_1 ( db_rec, arbelprm_cq_ci_db_record_st, 0,
|
||||||
|
counter, ( cq->next_idx & 0xffffffffUL ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Arbel Infiniband operations */
|
||||||
static struct ib_device_operations arbel_ib_operations = {
|
static struct ib_device_operations arbel_ib_operations = {
|
||||||
.post_send = arbel_post_send,
|
.post_send = arbel_post_send,
|
||||||
|
.poll_cq = arbel_poll_cq,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -63,6 +63,7 @@ struct ibhdr {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct ib_device;
|
||||||
|
|
||||||
/** An Infiniband Work Queue */
|
/** An Infiniband Work Queue */
|
||||||
struct ib_work_queue {
|
struct ib_work_queue {
|
||||||
|
@ -71,9 +72,11 @@ struct ib_work_queue {
|
||||||
/** Next work queue entry index
|
/** Next work queue entry index
|
||||||
*
|
*
|
||||||
* This is the index of the next entry to be filled (i.e. the
|
* This is the index of the next entry to be filled (i.e. the
|
||||||
* first empty entry).
|
* first empty entry). This value is not bounded by num_wqes;
|
||||||
|
* users must logical-AND with (num_wqes-1) to generate an
|
||||||
|
* array index.
|
||||||
*/
|
*/
|
||||||
unsigned int next_idx;
|
unsigned long next_idx;
|
||||||
/** I/O buffers assigned to work queue */
|
/** I/O buffers assigned to work queue */
|
||||||
struct io_buffer **iobufs;
|
struct io_buffer **iobufs;
|
||||||
/** Driver private data */
|
/** Driver private data */
|
||||||
|
@ -92,6 +95,38 @@ struct ib_queue_pair {
|
||||||
void *priv;
|
void *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** An Infiniband Completion Queue */
|
||||||
|
struct ib_completion_queue {
|
||||||
|
/** Number of completion queue entries */
|
||||||
|
unsigned int num_cqes;
|
||||||
|
/** Next completion queue entry index
|
||||||
|
*
|
||||||
|
* This is the index of the next entry to be filled (i.e. the
|
||||||
|
* first empty entry). This value is not bounded by num_wqes;
|
||||||
|
* users must logical-AND with (num_wqes-1) to generate an
|
||||||
|
* array index.
|
||||||
|
*/
|
||||||
|
unsigned long next_idx;
|
||||||
|
/** Driver private data */
|
||||||
|
void *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** An Infiniband completion */
|
||||||
|
struct ib_completion {
|
||||||
|
/** Length */
|
||||||
|
size_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** An Infiniband completion handler
|
||||||
|
*
|
||||||
|
* @v ibdev Infiniband device
|
||||||
|
* @v completion Completion
|
||||||
|
* @v iobuf I/O buffer
|
||||||
|
*/
|
||||||
|
typedef void ( * ib_completer_t ) ( struct ib_device *ibdev,
|
||||||
|
struct ib_completion *completion,
|
||||||
|
struct io_buffer *iobuf );
|
||||||
|
|
||||||
/** An Infiniband Address Vector */
|
/** An Infiniband Address Vector */
|
||||||
struct ib_address_vector {
|
struct ib_address_vector {
|
||||||
/** Destination Queue Pair */
|
/** Destination Queue Pair */
|
||||||
|
@ -110,15 +145,13 @@ struct ib_address_vector {
|
||||||
struct ib_gid gid;
|
struct ib_gid gid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ib_device;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Infiniband device operations
|
* Infiniband device operations
|
||||||
*
|
*
|
||||||
* These represent a subset of the Infiniband Verbs.
|
* These represent a subset of the Infiniband Verbs.
|
||||||
*/
|
*/
|
||||||
struct ib_device_operations {
|
struct ib_device_operations {
|
||||||
/** Post Send work queue entry
|
/** Post send work queue entry
|
||||||
*
|
*
|
||||||
* @v ibdev Infiniband device
|
* @v ibdev Infiniband device
|
||||||
* @v iobuf I/O buffer
|
* @v iobuf I/O buffer
|
||||||
|
@ -135,6 +168,19 @@ struct ib_device_operations {
|
||||||
struct io_buffer *iobuf,
|
struct io_buffer *iobuf,
|
||||||
struct ib_address_vector *av,
|
struct ib_address_vector *av,
|
||||||
struct ib_queue_pair *qp );
|
struct ib_queue_pair *qp );
|
||||||
|
/** Poll completion queue
|
||||||
|
*
|
||||||
|
* @v ibdev Infiniband device
|
||||||
|
* @v cq Completion queue
|
||||||
|
* @v complete_send Send completion handler
|
||||||
|
* @v complete_recv Receive completion handler
|
||||||
|
*
|
||||||
|
* The completion handler takes ownership of the I/O buffer.
|
||||||
|
*/
|
||||||
|
void ( * poll_cq ) ( struct ib_device *ibdev,
|
||||||
|
struct ib_completion_queue *cq,
|
||||||
|
ib_completer_t complete_send,
|
||||||
|
ib_completer_t complete_recv );
|
||||||
};
|
};
|
||||||
|
|
||||||
/** An Infiniband device */
|
/** An Infiniband device */
|
||||||
|
|
Reference in New Issue