david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

Updated MLX_* accessor macros to use implicit type information.

This commit is contained in:
Michael Brown 2007-09-15 18:44:09 +01:00
parent a3a91fedc1
commit 6a791649f0
4 changed files with 132 additions and 100 deletions

View File

@ -0,0 +1,39 @@
#ifndef _ARBEL_H
#define _ARBEL_H
struct MLX_DECLARE_STRUCT ( arbelprm_completion_queue_entry );
struct MLX_DECLARE_STRUCT ( arbelprm_completion_with_error );
struct MLX_DECLARE_STRUCT ( arbelprm_cq_ci_db_record );
struct MLX_DECLARE_STRUCT ( arbelprm_qp_db_record );
struct MLX_DECLARE_STRUCT ( arbelprm_send_doorbell );
struct MLX_DECLARE_STRUCT ( arbelprm_ud_address_vector );
struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_ctrl_send );
struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_data_ptr );
struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_next );
struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_ud );
#define ARBELPRM_MAX_GATHER 1
struct arbelprm_ud_send_wqe {
struct arbelprm_wqe_segment_next next;
struct arbelprm_wqe_segment_ctrl_send ctrl;
struct arbelprm_wqe_segment_ud ud;
struct arbelprm_wqe_segment_data_ptr data[ARBELPRM_MAX_GATHER];
} __attribute__ (( packed ));
union arbelprm_completion_entry {
struct arbelprm_completion_queue_entry normal;
struct arbelprm_completion_with_error error;
} __attribute__ (( packed ));
union arbelprm_doorbell_record {
struct arbelprm_cq_ci_db_record cq_ci;
struct arbelprm_qp_db_record qp;
} __attribute__ (( packed ));
union arbelprm_doorbell_register {
struct arbelprm_send_doorbell send;
uint32_t dword[2];
} __attribute__ (( packed ));
#endif /* _ARBEL_H */

View File

@ -143,8 +143,8 @@ struct addr_64_st {
* This structure provides a wrapper around the autogenerated * This structure provides a wrapper around the autogenerated
* pseudo_bit_t structures. It has the correct size, and also * pseudo_bit_t structures. It has the correct size, and also
* encapsulates type information about the underlying pseudo_bit_t * encapsulates type information about the underlying pseudo_bit_t
* structure, which allows the MLX_POPULATE etc. macros to work * structure, which allows the MLX_FILL etc. macros to work without
* without requiring explicit type information. * requiring explicit type information.
*/ */
#define MLX_DECLARE_STRUCT( _structure ) \ #define MLX_DECLARE_STRUCT( _structure ) \
_structure { \ _structure { \
@ -181,7 +181,8 @@ struct addr_64_st {
/** 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_st, _field ) \ #define MLX_BIT_MASK( _structure_st, _field ) \
( ( 1 << MLX_BIT_WIDTH ( _structure_st, _field ) ) - 1 ) ( ( ~( ( uint32_t ) 0 ) ) >> \
( 32 - MLX_BIT_WIDTH ( _structure_st, _field ) ) )
/* /*
* Assemble native-endian dword from named fields and values * Assemble native-endian dword from named fields and values
@ -229,46 +230,45 @@ struct addr_64_st {
* *
*/ */
#define MLX_POPULATE( _ptr, _index, _assembled ) \ #define MLX_FILL( _ptr, _index, _assembled ) \
do { \ do { \
uint32_t *__ptr = &(_ptr)->u.dwords[(_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( _ptr, _index, ... ) \ #define MLX_FILL_1( _ptr, _index, ... ) \
MLX_POPULATE ( _ptr, _index, \ MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_1 ( MLX_PSEUDO_STRUCT ( _ptr ),\
MLX_ASSEMBLE_1 ( MLX_PSEUDO_STRUCT ( _ptr ), \ _index, __VA_ARGS__ ) )
_index, __VA_ARGS__ ) )
#define MLX_POPULATE_2( _ptr, _index, ... ) \ #define MLX_FILL_2( _ptr, _index, ... ) \
MLX_POPULATE ( _ptr, _index, \ MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_2 ( MLX_PSEUDO_STRUCT ( _ptr ),\
MLX_ASSEMBLE_2 ( MLX_PSEUDO_STRUCT ( _ptr ), \ _index, __VA_ARGS__ ) )
_index, __VA_ARGS__ ) )
#define MLX_POPULATE_3( _ptr, _index, ... ) \ #define MLX_FILL_3( _ptr, _index, ... ) \
MLX_POPULATE ( _ptr, _index, \ MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_3 ( MLX_PSEUDO_STRUCT ( _ptr ),\
MLX_ASSEMBLE_3 ( MLX_PSEUDO_STRUCT ( _ptr ), \ _index, __VA_ARGS__ ) )
_index, __VA_ARGS__ ) )
#define MLX_FILL_4( _ptr, _index, ... ) \
MLX_FILL ( _ptr, _index, MLX_ASSEMBLE_4 ( MLX_PSEUDO_STRUCT ( _ptr ),\
_index, __VA_ARGS__ ) )
#define MLX_POPULATE_4( _ptr, _index, ... ) \
MLX_POPULATE ( _ptr, _index, \
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( _ptr, _index, _field, _value ) \ #define MLX_SET( _ptr, _field, _value ) \
do { \ do { \
uint32_t *__ptr = &(_ptr)->u.dwords[(_index)]; \ unsigned int __index = \
MLX_DWORD_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ), _field ); \
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 ( MLX_PSEUDO_STRUCT ( _ptr ), \ __value &= ~( MLX_MASK_1 ( MLX_PSEUDO_STRUCT ( _ptr ), \
_index, _field ) ); \ __index, _field ) ); \
__value |= MLX_ASSEMBLE_1 ( MLX_PSEUDO_STRUCT ( _ptr ), \ __value |= MLX_ASSEMBLE_1 ( MLX_PSEUDO_STRUCT ( _ptr ), \
_index, _field, _value ); \ __index, _field, _value ); \
*__ptr = cpu_to_be32 ( __value ); \ *__ptr = cpu_to_be32 ( __value ); \
} while ( 0 ) } while ( 0 )
@ -277,7 +277,7 @@ struct addr_64_st {
* *
*/ */
#define MLX_EXTRACT( _ptr, _field ) \ #define MLX_GET( _ptr, _field ) \
( { \ ( { \
unsigned int __index = \ unsigned int __index = \
MLX_DWORD_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ), _field ); \ MLX_DWORD_OFFSET ( MLX_PSEUDO_STRUCT ( _ptr ), _field ); \

View File

@ -37,14 +37,14 @@ struct arbel_completion_queue {
/** Doorbell record number */ /** Doorbell record number */
unsigned int doorbell_idx; unsigned int doorbell_idx;
/** Completion queue entries */ /** Completion queue entries */
union cqe_st *cqe; union arbelprm_completion_entry *cqe;
}; };
struct arbel { struct arbel {
/** User Access Region */ /** User Access Region */
void *uar; void *uar;
/** Doorbell records */ /** Doorbell records */
union db_record_st *db_rec; union arbelprm_doorbell_record *db_rec;
}; };
@ -157,9 +157,9 @@ static int mlx_transmit_direct ( struct net_device *netdev,
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, rlid ), .dlid = MLX_GET ( bav, rlid ),
.rate = ( MLX_EXTRACT ( bav, max_stat_rate ) ? 1 : 4 ), .rate = ( MLX_GET ( bav, max_stat_rate ) ? 1 : 4 ),
.sl = MLX_EXTRACT ( bav, sl ), .sl = MLX_GET ( bav, sl ),
.gid_present = 1, .gid_present = 1,
}; };
memcpy ( &av.gid, ( ( void * ) bav ) + 16, 16 ); memcpy ( &av.gid, ( ( void * ) bav ) + 16, 16 );
@ -318,18 +318,18 @@ static struct ib_gid arbel_no_gid = {
* @v db_reg Doorbell register structure * @v db_reg Doorbell register structure
* @v offset Address of doorbell * @v offset Address of doorbell
*/ */
static void arbel_ring_doorbell ( struct arbel *arbel, void *db_reg, static void arbel_ring_doorbell ( struct arbel *arbel,
union arbelprm_doorbell_register *db_reg,
unsigned int offset ) { unsigned int offset ) {
uint32_t *db_reg_dword = db_reg;
DBG ( "arbel_ring_doorbell %08lx:%08lx to %lx\n", DBG ( "arbel_ring_doorbell %08lx:%08lx to %lx\n",
db_reg_dword[0], db_reg_dword[1], db_reg->dword[0], db_reg->dword[1],
virt_to_phys ( arbel->uar + offset ) ); virt_to_phys ( arbel->uar + offset ) );
barrier(); barrier();
writel ( db_reg_dword[0], ( arbel->uar + offset + 0 ) ); writel ( db_reg->dword[0], ( arbel->uar + offset + 0 ) );
barrier(); barrier();
writel ( db_reg_dword[1], ( arbel->uar + offset + 4 ) ); writel ( db_reg->dword[1], ( arbel->uar + offset + 4 ) );
} }
/** /**
@ -347,15 +347,16 @@ static int arbel_post_send ( struct ib_device *ibdev, struct io_buffer *iobuf,
struct arbel *arbel = ibdev->priv; struct arbel *arbel = ibdev->priv;
struct ib_work_queue *wq = &qp->send; struct ib_work_queue *wq = &qp->send;
struct arbel_send_work_queue *arbel_wq = wq->priv; struct arbel_send_work_queue *arbel_wq = wq->priv;
unsigned int wqe_idx_mask = ( wq->num_wqes - 1 ); struct arbelprm_ud_send_wqe *prev_wqe;
struct ud_send_wqe_st *prev_wqe; struct arbelprm_ud_send_wqe *wqe;
struct ud_send_wqe_st *wqe; union arbelprm_doorbell_record *db_rec;
union arbelprm_doorbell_register db_reg;
struct ib_gid *gid; struct ib_gid *gid;
unsigned int wqe_idx_mask;
size_t nds; size_t nds;
union db_record_st *db_rec;
struct send_doorbell_st db_reg;
/* Allocate work queue entry */ /* Allocate work queue entry */
wqe_idx_mask = ( wq->num_wqes - 1 );
if ( wq->iobufs[wq->next_idx & wqe_idx_mask] ) { if ( wq->iobufs[wq->next_idx & wqe_idx_mask] ) {
DBGC ( arbel, "ARBEL %p send queue full", arbel ); DBGC ( arbel, "ARBEL %p send queue full", arbel );
return -ENOBUFS; return -ENOBUFS;
@ -365,69 +366,61 @@ static int arbel_post_send ( struct ib_device *ibdev, struct io_buffer *iobuf,
wqe = &arbel_wq->wqe_u[wq->next_idx & wqe_idx_mask].wqe_cont.wqe; wqe = &arbel_wq->wqe_u[wq->next_idx & wqe_idx_mask].wqe_cont.wqe;
/* Construct work queue entry */ /* Construct work queue entry */
MLX_POPULATE_1 ( &wqe->next.next, arbelprm_wqe_segment_next_st, 1, MLX_FILL_1 ( &wqe->next, 1, always1, 1 );
always1, 1 ); memset ( &wqe->ctrl, 0, sizeof ( wqe->ctrl ) );
memset ( &wqe->next.control, 0, MLX_FILL_1 ( &wqe->ctrl, 0, always1, 1 );
sizeof ( wqe->next.control ) ); memset ( &wqe->ud, 0, sizeof ( wqe->ud ) );
MLX_POPULATE_1 ( &wqe->next.control, MLX_FILL_2 ( &wqe->ud, 0,
arbelprm_wqe_segment_ctrl_send_st, 0, ud_address_vector.pd, GLOBAL_PD,
always1, 1 ); ud_address_vector.port_number, PXE_IB_PORT );
memset ( &wqe->udseg, 0, sizeof ( wqe->udseg ) ); MLX_FILL_2 ( &wqe->ud, 1,
MLX_POPULATE_2 ( &wqe->udseg, arbelprm_ud_address_vector_st, 0, ud_address_vector.rlid, av->dlid,
pd, GLOBAL_PD, ud_address_vector.g, av->gid_present );
port_number, PXE_IB_PORT ); MLX_FILL_2 ( &wqe->ud, 2,
MLX_POPULATE_2 ( &wqe->udseg, arbelprm_ud_address_vector_st, 1, ud_address_vector.max_stat_rate,
rlid, av->dlid, ( ( av->rate >= 3 ) ? 0 : 1 ),
g, av->gid_present ); ud_address_vector.msg, 3 );
MLX_POPULATE_2 ( &wqe->udseg, arbelprm_ud_address_vector_st, 2, MLX_FILL_1 ( &wqe->ud, 3, ud_address_vector.sl, av->sl );
max_stat_rate, ( ( av->rate >= 3 ) ? 0 : 1 ),
msg, 3 );
MLX_POPULATE_1 ( &wqe->udseg, arbelprm_ud_address_vector_st, 3,
sl, av->sl );
gid = ( av->gid_present ? &av->gid : &arbel_no_gid ); gid = ( av->gid_present ? &av->gid : &arbel_no_gid );
memcpy ( ( ( ( void * ) &wqe->udseg ) + 16 ), memcpy ( &wqe->ud.u.dwords[4], gid, sizeof ( *gid ) );
gid, sizeof ( *gid ) ); MLX_FILL_1 ( &wqe->ud, 8, destination_qp, av->dest_qp );
MLX_POPULATE_1 ( &wqe->udseg, arbelprm_wqe_segment_ud_st, 8, MLX_FILL_1 ( &wqe->ud, 9, q_key, av->qkey );
destination_qp, av->dest_qp ); MLX_FILL_1 ( &wqe->data[0], 3,
MLX_POPULATE_1 ( &wqe->udseg, arbelprm_wqe_segment_ud_st, 9, local_address_l, virt_to_bus ( iobuf->data ) );
q_key, av->qkey ); MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_len ( iobuf ) );
wqe->mpointer[0].local_addr_l =
cpu_to_be32 ( virt_to_bus ( iobuf->data ) );
wqe->mpointer[0].byte_count = cpu_to_be32 ( iob_len ( iobuf ) );
DBG ( "Work queue entry:\n" ); DBG ( "Work queue entry:\n" );
DBG_HD ( wqe, sizeof ( *wqe ) ); DBG_HD ( wqe, sizeof ( *wqe ) );
/* Update previous work queue entry's "next" field */ /* Update previous work queue entry's "next" field */
nds = ( ( offsetof ( typeof ( *wqe ), mpointer ) + nds = ( ( offsetof ( typeof ( *wqe ), data ) +
sizeof ( wqe->mpointer[0] ) ) >> 4 ); sizeof ( wqe->data[0] ) ) >> 4 );
MLX_MODIFY ( &prev_wqe->next.next, arbelprm_wqe_segment_next_st, 0, MLX_SET ( &prev_wqe->next, nopcode, XDEV_NOPCODE_SEND );
nopcode, XDEV_NOPCODE_SEND ); MLX_FILL_3 ( &prev_wqe->next, 1,
MLX_POPULATE_3 ( &prev_wqe->next.next, arbelprm_wqe_segment_next_st, 1, nds, nds,
nds, nds, f, 1,
f, 1, always1, 1 );
always1, 1 );
DBG ( "Previous work queue entry's next field:\n" ); DBG ( "Previous work queue entry's next field:\n" );
DBG_HD ( &prev_wqe->next.next, sizeof ( prev_wqe->next.next ) ); DBG_HD ( &prev_wqe->next, sizeof ( prev_wqe->next ) );
/* Update doorbell record */ /* Update doorbell record */
db_rec = &arbel->db_rec[arbel_wq->doorbell_idx]; db_rec = &arbel->db_rec[arbel_wq->doorbell_idx];
MLX_POPULATE_1 ( db_rec, arbelprm_qp_db_record_st, 0, MLX_FILL_1 ( &db_rec->qp, 0,
counter, ( ( wq->next_idx + 1 ) & 0xffff ) ); counter, ( ( wq->next_idx + 1 ) & 0xffff ) );
barrier(); barrier();
DBG ( "Doorbell record:\n" ); DBG ( "Doorbell record:\n" );
DBG_HD ( db_rec, 8 ); DBG_HD ( db_rec, 8 );
/* Ring doorbell register */ /* Ring doorbell register */
MLX_POPULATE_4 ( &db_reg, arbelprm_send_doorbell_st, 0, MLX_FILL_4 ( &db_reg.send, 0,
nopcode, XDEV_NOPCODE_SEND, nopcode, XDEV_NOPCODE_SEND,
f, 1, f, 1,
wqe_counter, ( wq->next_idx & 0xffff ), wqe_counter, ( wq->next_idx & 0xffff ),
wqe_cnt, 1 ); wqe_cnt, 1 );
MLX_POPULATE_2 ( &db_reg, arbelprm_send_doorbell_st, 1, MLX_FILL_2 ( &db_reg.send, 1,
nds, nds, nds, nds,
qpn, qp->qpn ); qpn, qp->qpn );
arbel_ring_doorbell ( arbel, &db_reg, POST_SND_OFFSET ); arbel_ring_doorbell ( arbel, &db_reg, POST_SND_OFFSET );
/* Update work queue's index */ /* Update work queue's index */
@ -437,13 +430,12 @@ static int arbel_post_send ( struct ib_device *ibdev, struct io_buffer *iobuf,
} }
static void arbel_parse_completion ( struct arbel *arbel, static void arbel_parse_completion ( struct arbel *arbel,
union cqe_st *cqe, union arbelprm_completion_entry *cqe,
struct ib_completion *completion ) { struct ib_completion *completion ) {
memset ( completion, 0, sizeof ( *completion ) ); memset ( completion, 0, sizeof ( *completion ) );
is_send = MLX_EXTRACT ( cqe, arbelprm_completion_queue_entry_st, s ); completion->is_send = MLX_GET ( &cqe->normal, s );
completion->len = completion->len = MLX_GET ( &cqe->normal, byte_cnt );
MLX_EXTRACT ( cqe, arbelprm_completion_queue_entry_st, }
byte_cnt );}
/** /**
* Poll completion queue * Poll completion queue
@ -459,8 +451,8 @@ static void arbel_poll_cq ( struct ib_device *ibdev,
struct arbel *arbel = ibdev->priv; struct arbel *arbel = ibdev->priv;
struct arbel_completion_queue *arbel_cq = cq->priv; struct arbel_completion_queue *arbel_cq = cq->priv;
unsigned int cqe_idx_mask = ( cq->num_cqes - 1 ); unsigned int cqe_idx_mask = ( cq->num_cqes - 1 );
union db_record_st *db_rec = &arbel->db_rec[arbel_cq->doorbell_idx]; union arbelprm_doorbell_record *db_rec;
union cqe_st *cqe; union arbelprm_completion_entry *cqe;
struct ib_completion completion; struct ib_completion completion;
struct io_buffer *iobuf; struct io_buffer *iobuf;
int is_send; int is_send;
@ -468,8 +460,7 @@ static void arbel_poll_cq ( struct ib_device *ibdev,
while ( 1 ) { while ( 1 ) {
/* Look for completion entry */ /* Look for completion entry */
cqe = &arbel_cq->cqe[cq->next_idx & cqe_idx_mask]; cqe = &arbel_cq->cqe[cq->next_idx & cqe_idx_mask];
if ( MLX_EXTRACT ( cqe, arbelprm_completion_queue_entry_st, if ( MLX_GET ( &cqe->normal, owner ) != 0 ) {
owner ) != 0 ) {
/* Entry still owned by hardware; end of poll */ /* Entry still owned by hardware; end of poll */
break; break;
} }
@ -484,14 +475,14 @@ static void arbel_poll_cq ( struct ib_device *ibdev,
iobuf ); iobuf );
/* Return ownership to hardware */ /* Return ownership to hardware */
MLX_POPULATE_1 ( cqe, arbelprm_completion_queue_entry_st, 7, MLX_FILL_1 ( &cqe->normal, 7, owner, 1 );
owner, 1 );
barrier(); barrier();
/* Update completion queue's index */ /* Update completion queue's index */
cq->next_idx++; cq->next_idx++;
/* Update doorbell record */ /* Update doorbell record */
MLX_POPULATE_1 ( db_rec, arbelprm_cq_ci_db_record_st, 0, db_rec = &arbel->db_rec[arbel_cq->doorbell_idx];
counter, ( cq->next_idx & 0xffffffffUL ) ); MLX_FILL_1 ( &db_rec->cq_ci, 0,
counter, ( cq->next_idx & 0xffffffffUL ) );
} }
} }

View File

@ -113,6 +113,8 @@ struct ib_completion_queue {
/** An Infiniband completion */ /** An Infiniband completion */
struct ib_completion { struct ib_completion {
/** Completion is for send queue */
int is_send;
/** Length */ /** Length */
size_t len; size_t len;
}; };