mirror of https://github.com/ipxe/ipxe.git
Gets a response out of the hardware. (An error completion, to be precise.)
parent
21d4ab3ce2
commit
8b27da9de1
|
@ -141,18 +141,33 @@ struct addr_64_st {
|
||||||
#define MLX_BIT_OFFSET( _structure, _field ) \
|
#define MLX_BIT_OFFSET( _structure, _field ) \
|
||||||
offsetof ( struct _structure, _field )
|
offsetof ( struct _structure, _field )
|
||||||
|
|
||||||
|
/** Dword offset of a field within a pseudo_bit_t structure */
|
||||||
|
#define MLX_DWORD_OFFSET( _structure, _field ) \
|
||||||
|
( MLX_BIT_OFFSET ( _structure, _field ) / 32 )
|
||||||
|
|
||||||
|
/** 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
|
||||||
|
* error of specifying a mismatched field name and dword index.
|
||||||
|
*/
|
||||||
|
#define MLX_DWORD_BIT_OFFSET( _structure, _index, _field ) \
|
||||||
|
( MLX_BIT_OFFSET ( _structure, _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, _field ) \
|
||||||
sizeof ( ( ( struct _structure * ) NULL )->_field )
|
sizeof ( ( ( struct _structure * ) NULL )->_field )
|
||||||
|
|
||||||
|
/** Bit mask for a field within a pseudo_bit_t structure */
|
||||||
|
#define MLX_BIT_MASK( _structure, _field ) \
|
||||||
|
( ( 1 << MLX_BIT_WIDTH ( _structure, _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, _index, _field, _value ) \
|
||||||
( (_value) << \
|
( (_value) << MLX_DWORD_BIT_OFFSET ( _structure, _index, _field ) )
|
||||||
( MLX_BIT_OFFSET ( _structure, _field ) - ( 32 * (_index) ) ) )
|
|
||||||
|
|
||||||
#define MLX_ASSEMBLE_2( _structure, _index, _field, _value, ... ) \
|
#define MLX_ASSEMBLE_2( _structure, _index, _field, _value, ... ) \
|
||||||
( MLX_ASSEMBLE_1 ( _structure, _index, _field, _value ) | \
|
( MLX_ASSEMBLE_1 ( _structure, _index, _field, _value ) | \
|
||||||
|
@ -172,9 +187,8 @@ struct addr_64_st {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MLX_MASK_1( _structure, _index, _field ) \
|
#define MLX_MASK_1( _structure, _index, _field ) \
|
||||||
MLX_ASSEMBLE_1 ( _structure, _index, _field, \
|
( MLX_BIT_MASK ( _structure, _field ) << \
|
||||||
( ( 1 << MLX_BIT_WIDTH ( _structure, \
|
MLX_DWORD_BIT_OFFSET ( _structure, _index, _field ) )
|
||||||
_field ) ) - 1 ) )
|
|
||||||
|
|
||||||
#define MLX_MASK_2( _structure, _index, _field, ... ) \
|
#define MLX_MASK_2( _structure, _index, _field, ... ) \
|
||||||
( MLX_MASK_1 ( _structure, _index, _field ) | \
|
( MLX_MASK_1 ( _structure, _index, _field ) | \
|
||||||
|
@ -231,4 +245,21 @@ struct addr_64_st {
|
||||||
*__ptr = cpu_to_be32 ( __value ); \
|
*__ptr = cpu_to_be32 ( __value ); \
|
||||||
} while ( 0 )
|
} while ( 0 )
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract value of named field
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MLX_EXTRACT( _base, _structure, _field ) \
|
||||||
|
( { \
|
||||||
|
unsigned int __index = \
|
||||||
|
MLX_DWORD_OFFSET ( _structure, _field ); \
|
||||||
|
uint32_t *__ptr = ( ( (uint32_t *) (_base) ) + __index ); \
|
||||||
|
uint32_t __value = be32_to_cpu ( *__ptr ); \
|
||||||
|
__value >>= MLX_DWORD_BIT_OFFSET ( _structure, __index, \
|
||||||
|
_field ); \
|
||||||
|
__value &= MLX_BIT_MASK ( _structure, _field ); \
|
||||||
|
__value; \
|
||||||
|
} )
|
||||||
|
|
||||||
#endif /* __bit_ops_h__ */
|
#endif /* __bit_ops_h__ */
|
||||||
|
|
|
@ -27,12 +27,13 @@ struct arbel_send_work_queue {
|
||||||
/** Doorbell number */
|
/** Doorbell 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arbel {
|
struct arbel {
|
||||||
/** User Access Region */
|
/** User Access Region */
|
||||||
unsigned long uar;
|
void *uar;
|
||||||
/** Doorbell records */
|
/** Doorbell records */
|
||||||
union db_record_st *db_rec;
|
union db_record_st *db_rec;
|
||||||
};
|
};
|
||||||
|
@ -88,7 +89,6 @@ static uint8_t ib_broadcast[IB_ALEN] = { 0xff, };
|
||||||
static int mlx_transmit ( struct net_device *netdev,
|
static int mlx_transmit ( struct net_device *netdev,
|
||||||
struct io_buffer *iobuf ) {
|
struct io_buffer *iobuf ) {
|
||||||
struct mlx_nic *mlx = netdev->priv;
|
struct mlx_nic *mlx = netdev->priv;
|
||||||
ud_av_t av = iobuf->data;
|
|
||||||
ud_send_wqe_t snd_wqe;
|
ud_send_wqe_t snd_wqe;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -110,6 +110,58 @@ static int mlx_transmit ( struct net_device *netdev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int arbel_post_send ( struct ib_device *ibdev, struct io_buffer *iobuf,
|
||||||
|
struct ib_address_vector *av,
|
||||||
|
struct ib_queue_pair *qp );
|
||||||
|
|
||||||
|
static struct io_buffer *tx_ring[NUM_IPOIB_SND_WQES];
|
||||||
|
static int tx_posted = 0;
|
||||||
|
|
||||||
|
static int mlx_transmit_direct ( struct net_device *netdev,
|
||||||
|
struct io_buffer *iobuf ) {
|
||||||
|
struct mlx_nic *mlx = netdev->priv;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
struct arbel arbel = {
|
||||||
|
.uar = memfree_pci_dev.uar,
|
||||||
|
.db_rec = dev_ib_data.uar_context_base,
|
||||||
|
};
|
||||||
|
struct arbel_send_work_queue arbel_send_queue = {
|
||||||
|
.doorbell_idx = IPOIB_SND_QP_DB_IDX,
|
||||||
|
.wqe_u = ( (struct udqp_st *) ipoib_data.ipoib_qph )->snd_wq,
|
||||||
|
};
|
||||||
|
struct ib_device ibdev = {
|
||||||
|
.priv = &arbel,
|
||||||
|
};
|
||||||
|
struct ib_queue_pair qp = {
|
||||||
|
.qpn = ib_get_qpn ( mlx->ipoib_qph ),
|
||||||
|
.send = {
|
||||||
|
.num_wqes = NUM_IPOIB_SND_WQES,
|
||||||
|
.posted = tx_posted,
|
||||||
|
.iobufs = tx_ring,
|
||||||
|
.priv = &arbel_send_queue,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
struct ud_av_st *bcast_av = mlx->bcast_av;
|
||||||
|
struct address_vector_st *bav = &bcast_av->av;
|
||||||
|
struct ib_address_vector av = {
|
||||||
|
.dest_qp = bcast_av->dest_qp,
|
||||||
|
.qkey = bcast_av->qkey,
|
||||||
|
.dlid = MLX_EXTRACT ( bav, arbelprm_ud_address_vector_st, rlid ),
|
||||||
|
.rate = ( MLX_EXTRACT ( bav, arbelprm_ud_address_vector_st, max_stat_rate ) ? 1 : 4 ),
|
||||||
|
.sl = MLX_EXTRACT ( bav, arbelprm_ud_address_vector_st, sl ),
|
||||||
|
.gid_present = 1,
|
||||||
|
};
|
||||||
|
memcpy ( &av.gid, ( ( void * ) bav ) + 16, 16 );
|
||||||
|
|
||||||
|
rc = arbel_post_send ( &ibdev, iobuf, &av, &qp );
|
||||||
|
|
||||||
|
tx_posted = qp.send.posted;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle TX completion
|
* Handle TX completion
|
||||||
*
|
*
|
||||||
|
@ -234,7 +286,7 @@ static void mlx_irq ( struct net_device *netdev, int enable ) {
|
||||||
static struct net_device_operations mlx_operations = {
|
static struct net_device_operations mlx_operations = {
|
||||||
.open = mlx_open,
|
.open = mlx_open,
|
||||||
.close = mlx_close,
|
.close = mlx_close,
|
||||||
.transmit = mlx_transmit,
|
.transmit = mlx_transmit_direct,
|
||||||
.poll = mlx_poll,
|
.poll = mlx_poll,
|
||||||
.irq = mlx_irq,
|
.irq = mlx_irq,
|
||||||
};
|
};
|
||||||
|
@ -274,12 +326,13 @@ static int arbel_post_send ( struct ib_device *ibdev, struct io_buffer *iobuf,
|
||||||
/* Allocate work queue entry */
|
/* Allocate work queue entry */
|
||||||
prev_wqe_idx = wq->posted;
|
prev_wqe_idx = wq->posted;
|
||||||
wqe_idx = ( prev_wqe_idx + 1 );
|
wqe_idx = ( prev_wqe_idx + 1 );
|
||||||
if ( wq->iobuf[wqe_idx & wqe_idx_mask] ) {
|
if ( wq->iobufs[wqe_idx & wqe_idx_mask] ) {
|
||||||
DBGC ( arbel, "ARBEL %p send queue full", arbel );
|
DBGC ( arbel, "ARBEL %p send queue full", arbel );
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
}
|
}
|
||||||
prev_wqe = &arbel_wq->wqe[prev_wqe_idx & wqe_idx_mask];
|
wq->iobufs[wqe_idx & wqe_idx_mask] = iobuf;
|
||||||
wqe = &arbel_wq->wqe[wqe_idx & wqe_idx_mask];
|
prev_wqe = &arbel_wq->wqe_u[prev_wqe_idx & wqe_idx_mask].wqe_cont.wqe;
|
||||||
|
wqe = &arbel_wq->wqe_u[wqe_idx & wqe_idx_mask].wqe_cont.wqe;
|
||||||
|
|
||||||
/* Construct work queue entry */
|
/* Construct work queue entry */
|
||||||
memset ( &wqe->next.control, 0,
|
memset ( &wqe->next.control, 0,
|
||||||
|
|
|
@ -73,10 +73,10 @@ struct ib_work_queue {
|
||||||
* This is the index of the most recently posted entry.
|
* This is the index of the most recently posted entry.
|
||||||
*/
|
*/
|
||||||
unsigned int posted;
|
unsigned int posted;
|
||||||
|
/** I/O buffers assigned to work queue */
|
||||||
|
struct io_buffer **iobufs;
|
||||||
/** Driver private data */
|
/** Driver private data */
|
||||||
void *priv;
|
void *priv;
|
||||||
/** I/O buffers assigned to work queue */
|
|
||||||
struct io_buffer *iobuf[0];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** An Infiniband Queue Pair */
|
/** An Infiniband Queue Pair */
|
||||||
|
|
Loading…
Reference in New Issue