david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

Revert to dev_priv/owner_priv scheme, rather than container_of; it

makes it easier to put the generic allocation code into infiniband.c
This commit is contained in:
Michael Brown 2007-09-16 17:25:15 +01:00
parent e238bb1e43
commit b21d4ca21e
4 changed files with 221 additions and 107 deletions

View File

@ -107,6 +107,8 @@ struct arbel_dev_limits {
unsigned long reserved_uars; unsigned long reserved_uars;
/** Number of reserved CQs */ /** Number of reserved CQs */
unsigned long reserved_cqs; unsigned long reserved_cqs;
/** Number of reserved QPs */
unsigned long reserved_qps;
}; };
/** Alignment of Arbel send work queue entries */ /** Alignment of Arbel send work queue entries */
@ -143,6 +145,15 @@ struct arbel_recv_work_queue {
union arbel_recv_wqe *wqe; union arbel_recv_wqe *wqe;
}; };
/** Maximum number of allocatable queue pairs
*
* This is a policy decision, not a device limit.
*/
#define ARBEL_MAX_QPS 8
/** Base queue pair number */
#define ARBEL_QPN_BASE 0x550000
/** An Arbel queue pair */ /** An Arbel queue pair */
struct arbel_queue_pair { struct arbel_queue_pair {
/** Infiniband queue pair */ /** Infiniband queue pair */
@ -161,10 +172,10 @@ struct arbel_queue_pair {
/** An Arbel completion queue */ /** An Arbel completion queue */
struct arbel_completion_queue { struct arbel_completion_queue {
/** Infiniband completion queue */ /** Consumer counter doorbell record number */
struct ib_completion_queue cq; unsigned int ci_doorbell_idx;
/** Doorbell record number */ /** Arm queue doorbell record number */
unsigned int doorbell_idx; unsigned int arm_doorbell_idx;
/** Completion queue entries */ /** Completion queue entries */
union arbelprm_completion_entry *cqe; union arbelprm_completion_entry *cqe;
}; };
@ -200,6 +211,8 @@ struct arbel {
/** Completion queue in-use bitmask */ /** Completion queue in-use bitmask */
arbel_bitmask_t cq_inuse[ ARBEL_BITMASK_SIZE ( ARBEL_MAX_CQS ) ]; arbel_bitmask_t cq_inuse[ ARBEL_BITMASK_SIZE ( ARBEL_MAX_CQS ) ];
/** Queue pair in-use bitmask */
arbel_bitmask_t qp_inuse[ ARBEL_BITMASK_SIZE ( ARBEL_MAX_QPS ) ];
/** Device limits */ /** Device limits */
struct arbel_dev_limits limits; struct arbel_dev_limits limits;
@ -301,7 +314,7 @@ arbel_recv_doorbell_idx ( unsigned int qpn_offset ) {
} }
/** /**
* Get commpletion queue consumer counter doorbell index * Get completion queue consumer counter doorbell index
* *
* @v cqn_offset Completion queue number offset * @v cqn_offset Completion queue number offset
* @ret doorbell_idx Doorbell index * @ret doorbell_idx Doorbell index

View File

@ -53,28 +53,28 @@ static struct io_buffer *static_ipoib_tx_ring[NUM_IPOIB_SND_WQES];
static struct io_buffer *static_ipoib_rx_ring[NUM_IPOIB_RCV_WQES]; static struct io_buffer *static_ipoib_rx_ring[NUM_IPOIB_RCV_WQES];
static struct arbel static_arbel; static struct arbel static_arbel;
static struct arbel_completion_queue static_ipoib_send_cq;
static struct arbel_completion_queue static_ipoib_recv_cq;
static struct arbel_queue_pair static_ipoib_qp = { static struct arbel_completion_queue static_arbel_ipoib_send_cq = {
.qp = { .ci_doorbell_idx = IPOIB_SND_CQ_CI_DB_IDX,
.send = { };
.qp = &static_ipoib_qp.qp, static struct ib_completion_queue static_ipoib_send_cq = {
.is_send = 1, .cqn = 1234, /* Only used for debug messages */
.cq = &static_ipoib_send_cq.cq, .num_cqes = NUM_IPOIB_SND_CQES,
.num_wqes = NUM_IPOIB_SND_WQES, .work_queues = LIST_HEAD_INIT ( static_ipoib_send_cq.work_queues ),
.iobufs = static_ipoib_tx_ring, .dev_priv = &static_arbel_ipoib_send_cq,
.list = LIST_HEAD_INIT (static_ipoib_qp.qp.send.list), };
},
.recv = { static struct arbel_completion_queue static_arbel_ipoib_recv_cq = {
.qp = &static_ipoib_qp.qp, .ci_doorbell_idx = IPOIB_RCV_CQ_CI_DB_IDX,
.is_send = 0, };
.cq = &static_ipoib_recv_cq.cq, static struct ib_completion_queue static_ipoib_recv_cq = {
.num_wqes = NUM_IPOIB_RCV_WQES, .cqn = 2345, /* Only used for debug messages */
.iobufs = static_ipoib_rx_ring, .num_cqes = NUM_IPOIB_RCV_CQES,
.list = LIST_HEAD_INIT (static_ipoib_qp.qp.recv.list), .work_queues = LIST_HEAD_INIT ( static_ipoib_recv_cq.work_queues ),
}, .dev_priv = &static_arbel_ipoib_recv_cq,
}, };
static struct arbel_queue_pair static_arbel_ipoib_qp = {
.send = { .send = {
.doorbell_idx = IPOIB_SND_QP_DB_IDX, .doorbell_idx = IPOIB_SND_QP_DB_IDX,
}, },
@ -82,24 +82,31 @@ static struct arbel_queue_pair static_ipoib_qp = {
.doorbell_idx = IPOIB_RCV_QP_DB_IDX, .doorbell_idx = IPOIB_RCV_QP_DB_IDX,
}, },
}; };
static struct arbel_completion_queue static_ipoib_send_cq = { static struct ib_queue_pair static_ipoib_qp = {
.cq = { .send = {
.cqn = 1234, /* Only used for debug messages */ .qp = &static_ipoib_qp,
.num_cqes = NUM_IPOIB_SND_CQES, .is_send = 1,
.work_queues = LIST_HEAD_INIT (static_ipoib_send_cq.cq.work_queues), .cq = &static_ipoib_send_cq,
.num_wqes = NUM_IPOIB_SND_WQES,
.iobufs = static_ipoib_tx_ring,
.list = LIST_HEAD_INIT (static_ipoib_qp.send.list),
.dev_priv = &static_arbel_ipoib_qp.send,
}, },
.doorbell_idx = IPOIB_SND_CQ_CI_DB_IDX, .recv = {
}; .qp = &static_ipoib_qp,
static struct arbel_completion_queue static_ipoib_recv_cq = { .is_send = 0,
.cq = { .cq = &static_ipoib_recv_cq,
.cqn = 2345, /* Only used for debug messages */ .num_wqes = NUM_IPOIB_RCV_WQES,
.num_cqes = NUM_IPOIB_RCV_CQES, .iobufs = static_ipoib_rx_ring,
.work_queues = LIST_HEAD_INIT (static_ipoib_recv_cq.cq.work_queues), .list = LIST_HEAD_INIT (static_ipoib_qp.recv.list),
.dev_priv = &static_arbel_ipoib_qp.recv,
}, },
.doorbell_idx = IPOIB_RCV_CQ_CI_DB_IDX, .dev_priv = &static_arbel_ipoib_qp,
}; };
static struct ib_device static_ibdev = { static struct ib_device static_ibdev = {
.priv = &static_arbel, .dev_priv = &static_arbel,
}; };
@ -150,7 +157,7 @@ static int mlx_transmit_direct ( struct net_device *netdev,
}; };
memcpy ( &av.gid, ( ( void * ) bav ) + 16, 16 ); memcpy ( &av.gid, ( ( void * ) bav ) + 16, 16 );
rc = arbel_post_send ( &static_ibdev, &static_ipoib_qp.qp, &av, iobuf ); rc = arbel_post_send ( &static_ibdev, &static_ipoib_qp, &av, iobuf );
return rc; return rc;
} }
@ -164,7 +171,7 @@ static void temp_complete_send ( struct ib_device *ibdev __unused,
struct ib_queue_pair *qp, struct ib_queue_pair *qp,
struct ib_completion *completion, struct ib_completion *completion,
struct io_buffer *iobuf ) { struct io_buffer *iobuf ) {
struct net_device *netdev = qp->priv; struct net_device *netdev = qp->owner_priv;
DBG ( "Wahey! TX completion\n" ); DBG ( "Wahey! TX completion\n" );
netdev_tx_complete_err ( netdev, iobuf, netdev_tx_complete_err ( netdev, iobuf,
@ -175,7 +182,7 @@ static void temp_complete_recv ( struct ib_device *ibdev __unused,
struct ib_queue_pair *qp, struct ib_queue_pair *qp,
struct ib_completion *completion, struct ib_completion *completion,
struct io_buffer *iobuf ) { struct io_buffer *iobuf ) {
struct net_device *netdev = qp->priv; struct net_device *netdev = qp->owner_priv;
struct mlx_nic *mlx = netdev->priv; struct mlx_nic *mlx = netdev->priv;
DBG ( "Yay! RX completion on %p len %zx:\n", iobuf, completion->len ); DBG ( "Yay! RX completion on %p len %zx:\n", iobuf, completion->len );
@ -205,7 +212,7 @@ static void mlx_refill_rx ( struct net_device *netdev ) {
break; break;
DBG ( "Posting RX buffer %p:\n", iobuf ); DBG ( "Posting RX buffer %p:\n", iobuf );
if ( ( rc = arbel_post_recv ( &static_ibdev, if ( ( rc = arbel_post_recv ( &static_ibdev,
&static_ipoib_qp.qp, &static_ipoib_qp,
iobuf ) ) != 0 ) { iobuf ) ) != 0 ) {
free_iob ( iobuf ); free_iob ( iobuf );
break; break;
@ -237,11 +244,10 @@ static void mlx_poll ( struct net_device *netdev ) {
} }
/* Poll completion queues */ /* Poll completion queues */
arbel_poll_cq ( &static_ibdev, &static_ipoib_send_cq.cq, arbel_poll_cq ( &static_ibdev, &static_ipoib_send_cq,
temp_complete_send, temp_complete_recv ); temp_complete_send, temp_complete_recv );
arbel_poll_cq ( &static_ibdev, &static_ipoib_recv_cq.cq, arbel_poll_cq ( &static_ibdev, &static_ipoib_recv_cq,
temp_complete_send, temp_complete_recv ); temp_complete_send, temp_complete_recv );
// mlx_poll_cq ( netdev, mlx->rcv_cqh, mlx_rx_complete );
mlx_refill_rx ( netdev ); mlx_refill_rx ( netdev );
} }
@ -469,24 +475,18 @@ arbel_cmd_hw2sw_cq ( struct arbel *arbel, unsigned long cqn ) {
* Create completion queue * Create completion queue
* *
* @v ibdev Infiniband device * @v ibdev Infiniband device
* @v log2_num_cqes Log2 of the number of completion queue entries * @v cq Completion queue
* @ret new_cq New completion queue
* @ret rc Return status code * @ret rc Return status code
*/ */
static int arbel_create_cq ( struct ib_device *ibdev, static int arbel_create_cq ( struct ib_device *ibdev,
unsigned int log2_num_cqes, struct ib_completion_queue *cq ) {
struct ib_completion_queue **new_cq ) { struct arbel *arbel = ibdev->dev_priv;
struct arbel *arbel = ibdev->priv;
struct arbel_completion_queue *arbel_cq; struct arbel_completion_queue *arbel_cq;
struct arbelprm_completion_queue_context cqctx; struct arbelprm_completion_queue_context cqctx;
struct arbelprm_cq_ci_db_record *ci_db_rec; struct arbelprm_cq_ci_db_record *ci_db_rec;
struct arbelprm_cq_arm_db_record *arm_db_rec; struct arbelprm_cq_arm_db_record *arm_db_rec;
int cqn_offset; int cqn_offset;
unsigned int cqn;
unsigned int num_cqes;
size_t cqe_size; size_t cqe_size;
unsigned int ci_doorbell_idx;
unsigned int arm_doorbell_idx;
unsigned int i; unsigned int i;
int rc; int rc;
@ -497,9 +497,7 @@ static int arbel_create_cq ( struct ib_device *ibdev,
rc = cqn_offset; rc = cqn_offset;
goto err_cqn_offset; goto err_cqn_offset;
} }
cqn = ( arbel->limits.reserved_cqs + cqn_offset ); cq->cqn = ( arbel->limits.reserved_cqs + cqn_offset );
ci_doorbell_idx = arbel_cq_ci_doorbell_idx ( cqn_offset );
arm_doorbell_idx = arbel_cq_arm_doorbell_idx ( cqn_offset );
/* Allocate control structures */ /* Allocate control structures */
arbel_cq = zalloc ( sizeof ( *arbel_cq ) ); arbel_cq = zalloc ( sizeof ( *arbel_cq ) );
@ -507,58 +505,59 @@ static int arbel_create_cq ( struct ib_device *ibdev,
rc = -ENOMEM; rc = -ENOMEM;
goto err_arbel_cq; goto err_arbel_cq;
} }
arbel_cq->cq.cqn = cqn; arbel_cq->ci_doorbell_idx = arbel_cq_ci_doorbell_idx ( cqn_offset );
arbel_cq->cq.num_cqes = num_cqes; arbel_cq->arm_doorbell_idx = arbel_cq_arm_doorbell_idx ( cqn_offset );
INIT_LIST_HEAD ( &arbel_cq->cq.work_queues );
arbel_cq->doorbell_idx = ci_doorbell_idx;
/* Allocate completion queue itself */ /* Allocate completion queue itself */
num_cqes = ( 1 << log2_num_cqes ); cqe_size = ( cq->num_cqes * sizeof ( arbel_cq->cqe[0] ) );
cqe_size = ( num_cqes * sizeof ( arbel_cq->cqe[0] ) );
arbel_cq->cqe = malloc_dma ( cqe_size, sizeof ( arbel_cq->cqe[0] ) ); arbel_cq->cqe = malloc_dma ( cqe_size, sizeof ( arbel_cq->cqe[0] ) );
if ( ! arbel_cq->cqe ) { if ( ! arbel_cq->cqe ) {
rc = -ENOMEM; rc = -ENOMEM;
goto err_cqe; goto err_cqe;
} }
memset ( arbel_cq->cqe, 0, cqe_size ); memset ( arbel_cq->cqe, 0, cqe_size );
for ( i = 0 ; i < num_cqes ; i++ ) { for ( i = 0 ; i < cq->num_cqes ; i++ ) {
MLX_FILL_1 ( &arbel_cq->cqe[i].normal, 7, owner, 1 ); MLX_FILL_1 ( &arbel_cq->cqe[i].normal, 7, owner, 1 );
} }
barrier(); barrier();
/* Initialise doorbell records */ /* Initialise doorbell records */
ci_db_rec = &arbel->db_rec[ci_doorbell_idx].cq_ci; ci_db_rec = &arbel->db_rec[arbel_cq->ci_doorbell_idx].cq_ci;
MLX_FILL_1 ( ci_db_rec, 0, counter, 0 ); MLX_FILL_1 ( ci_db_rec, 0, counter, 0 );
MLX_FILL_2 ( ci_db_rec, 1, MLX_FILL_2 ( ci_db_rec, 1,
res, ARBEL_UAR_RES_CQ_CI, res, ARBEL_UAR_RES_CQ_CI,
cq_number, cqn ); cq_number, cq->cqn );
arm_db_rec = &arbel->db_rec[arm_doorbell_idx].cq_arm; arm_db_rec = &arbel->db_rec[arbel_cq->arm_doorbell_idx].cq_arm;
MLX_FILL_1 ( arm_db_rec, 0, counter, 0 ); MLX_FILL_1 ( arm_db_rec, 0, counter, 0 );
MLX_FILL_2 ( arm_db_rec, 1, MLX_FILL_2 ( arm_db_rec, 1,
res, ARBEL_UAR_RES_CQ_ARM, res, ARBEL_UAR_RES_CQ_ARM,
cq_number, cqn ); cq_number, cq->cqn );
/* Hand queue over to hardware */ /* Hand queue over to hardware */
memset ( &cqctx, 0, sizeof ( cqctx ) ); memset ( &cqctx, 0, sizeof ( cqctx ) );
MLX_FILL_1 ( &cqctx, 0, st, 0xa /* "Event fired" */ ); MLX_FILL_1 ( &cqctx, 0, st, 0xa /* "Event fired" */ );
MLX_FILL_1 ( &cqctx, 2, start_address_l, MLX_FILL_1 ( &cqctx, 2, start_address_l,
virt_to_bus ( arbel_cq->cqe ) ); virt_to_bus ( arbel_cq->cqe ) );
#if 0
MLX_FILL_2 ( &cqctx, 3, MLX_FILL_2 ( &cqctx, 3,
usr_page, arbel->limits.reserved_uars, usr_page, arbel->limits.reserved_uars,
log_cq_size, log2_num_cqes ); log_cq_size, log2_num_cqes );
#endif
MLX_FILL_1 ( &cqctx, 5, c_eqn, arbel->eqn ); MLX_FILL_1 ( &cqctx, 5, c_eqn, arbel->eqn );
MLX_FILL_1 ( &cqctx, 6, pd, ARBEL_GLOBAL_PD ); MLX_FILL_1 ( &cqctx, 6, pd, ARBEL_GLOBAL_PD );
MLX_FILL_1 ( &cqctx, 7, l_key, arbel->reserved_lkey ); MLX_FILL_1 ( &cqctx, 7, l_key, arbel->reserved_lkey );
MLX_FILL_1 ( &cqctx, 12, cqn, cqn ); MLX_FILL_1 ( &cqctx, 12, cqn, cq->cqn );
MLX_FILL_1 ( &cqctx, 13, cq_ci_db_record, ci_doorbell_idx ); MLX_FILL_1 ( &cqctx, 13,
MLX_FILL_1 ( &cqctx, 14, cq_state_db_record, arm_doorbell_idx ); cq_ci_db_record, arbel_cq->ci_doorbell_idx );
if ( ( rc = arbel_cmd_sw2hw_cq ( arbel, cqn, &cqctx ) ) != 0 ) { MLX_FILL_1 ( &cqctx, 14,
cq_state_db_record, arbel_cq->arm_doorbell_idx );
if ( ( rc = arbel_cmd_sw2hw_cq ( arbel, cq->cqn, &cqctx ) ) != 0 ) {
DBGC ( arbel, "Arbel %p SW2HW_CQ failed: %s\n", DBGC ( arbel, "Arbel %p SW2HW_CQ failed: %s\n",
arbel, strerror ( rc ) ); arbel, strerror ( rc ) );
goto err_sw2hw; goto err_sw2hw;
} }
*new_cq = &arbel_cq->cq; cq->dev_priv = arbel_cq;
return 0; return 0;
err_sw2hw: err_sw2hw:
@ -581,9 +580,8 @@ static int arbel_create_cq ( struct ib_device *ibdev,
*/ */
static void arbel_destroy_cq ( struct ib_device *ibdev, static void arbel_destroy_cq ( struct ib_device *ibdev,
struct ib_completion_queue *cq ) { struct ib_completion_queue *cq ) {
struct arbel *arbel = ibdev->priv; struct arbel *arbel = ibdev->dev_priv;
struct arbel_completion_queue *arbel_cq = struct arbel_completion_queue *arbel_cq = cq->dev_priv;
container_of ( cq, struct arbel_completion_queue, cq );
struct arbelprm_cq_ci_db_record *ci_db_rec; struct arbelprm_cq_ci_db_record *ci_db_rec;
struct arbelprm_cq_arm_db_record *arm_db_rec; struct arbelprm_cq_arm_db_record *arm_db_rec;
int cqn_offset; int cqn_offset;
@ -618,6 +616,53 @@ static void arbel_destroy_cq ( struct ib_device *ibdev,
arbel_free_qn_offset ( arbel->cq_inuse, cqn_offset ); arbel_free_qn_offset ( arbel->cq_inuse, cqn_offset );
} }
/***************************************************************************
*
* Queue pair operations
*
***************************************************************************
*/
static int arbel_create_qp ( struct ib_device *ibdev,
unsigned int log2_num_send_wqes,
struct ib_completion_queue *send_cq,
unsigned int log2_num_recv_wqes,
struct ib_completion_queue *recv_cq,
struct ib_queue_pair **new_qp ) {
struct arbel *arbel = ibdev->dev_priv;
struct arbel_queue_pair *arbel_qp;
struct arbelprm_qp_db_record *send_db_rec;
struct arbelprm_qp_db_record *recv_db_rec;
int qpn_offset;
unsigned int qpn;
unsigned int num_send_wqes;
unsigned int num_recv_wqes;
unsigned int send_doorbell_idx;
unsigned int recv_doorbell_idx;
int rc;
/* Find a free queue pair number */
qpn_offset = arbel_alloc_qn_offset ( arbel->qp_inuse, ARBEL_MAX_QPS );
if ( qpn_offset < 0 ) {
DBGC ( arbel, "Arbel %p out of queue pairs\n", arbel );
rc = qpn_offset;
goto err_qpn_offset;
}
qpn = ( ARBEL_QPN_BASE + arbel->limits.reserved_qps + qpn_offset );
send_doorbell_idx = arbel_send_doorbell_idx ( qpn_offset );
recv_doorbell_idx = arbel_recv_doorbell_idx ( qpn_offset );
/* Allocate control structures */
num_send_wqes = ( 1 << log2_num_send_wqes );
num_recv_wqes = ( 1 << log2_num_recv_wqes );
arbel_qp = zalloc ( sizeof ( *arbel_qp ) );
return 0;
err_qpn_offset:
return rc;
}
/*************************************************************************** /***************************************************************************
* *
* Work request operations * Work request operations
@ -659,9 +704,8 @@ static int arbel_post_send ( struct ib_device *ibdev,
struct ib_queue_pair *qp, struct ib_queue_pair *qp,
struct ib_address_vector *av, struct ib_address_vector *av,
struct io_buffer *iobuf ) { struct io_buffer *iobuf ) {
struct arbel *arbel = ibdev->priv; struct arbel *arbel = ibdev->dev_priv;
struct arbel_queue_pair *arbel_qp struct arbel_queue_pair *arbel_qp = qp->dev_priv;
= container_of ( qp, struct arbel_queue_pair, qp );
struct ib_work_queue *wq = &qp->send; struct ib_work_queue *wq = &qp->send;
struct arbel_send_work_queue *arbel_send_wq = &arbel_qp->send; struct arbel_send_work_queue *arbel_send_wq = &arbel_qp->send;
struct arbelprm_ud_send_wqe *prev_wqe; struct arbelprm_ud_send_wqe *prev_wqe;
@ -749,9 +793,8 @@ static int arbel_post_send ( struct ib_device *ibdev,
static int arbel_post_recv ( struct ib_device *ibdev, static int arbel_post_recv ( struct ib_device *ibdev,
struct ib_queue_pair *qp, struct ib_queue_pair *qp,
struct io_buffer *iobuf ) { struct io_buffer *iobuf ) {
struct arbel *arbel = ibdev->priv; struct arbel *arbel = ibdev->dev_priv;
struct arbel_queue_pair *arbel_qp struct arbel_queue_pair *arbel_qp = qp->dev_priv;
= container_of ( qp, struct arbel_queue_pair, qp );
struct ib_work_queue *wq = &qp->recv; struct ib_work_queue *wq = &qp->recv;
struct arbel_recv_work_queue *arbel_recv_wq = &arbel_qp->recv; struct arbel_recv_work_queue *arbel_recv_wq = &arbel_qp->recv;
struct arbelprm_recv_wqe *wqe; struct arbelprm_recv_wqe *wqe;
@ -800,7 +843,7 @@ static int arbel_complete ( struct ib_device *ibdev,
union arbelprm_completion_entry *cqe, union arbelprm_completion_entry *cqe,
ib_completer_t complete_send, ib_completer_t complete_send,
ib_completer_t complete_recv ) { ib_completer_t complete_recv ) {
struct arbel *arbel = ibdev->priv; struct arbel *arbel = ibdev->dev_priv;
struct ib_completion completion; struct ib_completion completion;
struct ib_work_queue *wq; struct ib_work_queue *wq;
struct ib_queue_pair *qp; struct ib_queue_pair *qp;
@ -842,7 +885,7 @@ static int arbel_complete ( struct ib_device *ibdev,
return -EIO; return -EIO;
} }
qp = wq->qp; qp = wq->qp;
arbel_qp = container_of ( qp, struct arbel_queue_pair, qp ); arbel_qp = qp->dev_priv;
/* Identify work queue entry index */ /* Identify work queue entry index */
if ( is_send ) { if ( is_send ) {
@ -883,9 +926,8 @@ static void arbel_poll_cq ( struct ib_device *ibdev,
struct ib_completion_queue *cq, struct ib_completion_queue *cq,
ib_completer_t complete_send, ib_completer_t complete_send,
ib_completer_t complete_recv ) { ib_completer_t complete_recv ) {
struct arbel *arbel = ibdev->priv; struct arbel *arbel = ibdev->dev_priv;
struct arbel_completion_queue *arbel_cq struct arbel_completion_queue *arbel_cq = cq->dev_priv;
= container_of ( cq, struct arbel_completion_queue, cq );
struct arbelprm_cq_ci_db_record *ci_db_rec; struct arbelprm_cq_ci_db_record *ci_db_rec;
union arbelprm_completion_entry *cqe; union arbelprm_completion_entry *cqe;
unsigned int cqe_idx_mask; unsigned int cqe_idx_mask;
@ -914,7 +956,7 @@ static void arbel_poll_cq ( struct ib_device *ibdev,
/* Update completion queue's index */ /* Update completion queue's index */
cq->next_idx++; cq->next_idx++;
/* Update doorbell record */ /* Update doorbell record */
ci_db_rec = &arbel->db_rec[arbel_cq->doorbell_idx].cq_ci; ci_db_rec = &arbel->db_rec[arbel_cq->ci_doorbell_idx].cq_ci;
MLX_FILL_1 ( ci_db_rec, 0, MLX_FILL_1 ( ci_db_rec, 0,
counter, ( cq->next_idx & 0xffffffffUL ) ); counter, ( cq->next_idx & 0xffffffffUL ) );
} }
@ -992,20 +1034,20 @@ static int arbel_probe ( struct pci_device *pci,
arbel->db_rec = dev_ib_data.uar_context_base; arbel->db_rec = dev_ib_data.uar_context_base;
arbel->reserved_lkey = dev_ib_data.mkey; arbel->reserved_lkey = dev_ib_data.mkey;
arbel->eqn = dev_ib_data.eq.eqn; arbel->eqn = dev_ib_data.eq.eqn;
static_ipoib_qp.send.wqe = static_arbel_ipoib_qp.send.wqe =
( ( struct udqp_st * ) qph )->snd_wq; ( ( struct udqp_st * ) qph )->snd_wq;
static_ipoib_qp.recv.wqe = static_arbel_ipoib_qp.recv.wqe =
( ( struct udqp_st * ) qph )->rcv_wq; ( ( struct udqp_st * ) qph )->rcv_wq;
static_ipoib_send_cq.cqe = static_arbel_ipoib_send_cq.cqe =
( ( struct cq_st * ) ib_data.ipoib_snd_cq )->cq_buf; ( ( struct cq_st * ) ib_data.ipoib_snd_cq )->cq_buf;
static_ipoib_recv_cq.cqe = static_arbel_ipoib_recv_cq.cqe =
( ( struct cq_st * ) ib_data.ipoib_rcv_cq )->cq_buf; ( ( struct cq_st * ) ib_data.ipoib_rcv_cq )->cq_buf;
static_ipoib_qp.qp.qpn = ib_get_qpn ( qph ); static_ipoib_qp.qpn = ib_get_qpn ( qph );
static_ipoib_qp.qp.priv = netdev; static_ipoib_qp.owner_priv = netdev;
list_add ( &static_ipoib_qp.qp.send.list, list_add ( &static_ipoib_qp.send.list,
&static_ipoib_send_cq.cq.work_queues ); &static_ipoib_send_cq.work_queues );
list_add ( &static_ipoib_qp.qp.recv.list, list_add ( &static_ipoib_qp.recv.list,
&static_ipoib_recv_cq.cq.work_queues ); &static_ipoib_recv_cq.work_queues );
/* Get device limits */ /* Get device limits */
if ( ( rc = arbel_cmd_query_dev_lim ( arbel, &dev_lim ) ) != 0 ) { if ( ( rc = arbel_cmd_query_dev_lim ( arbel, &dev_lim ) ) != 0 ) {
@ -1016,6 +1058,8 @@ static int arbel_probe ( struct pci_device *pci,
arbel->limits.reserved_uars = MLX_GET ( &dev_lim, num_rsvd_uars ); arbel->limits.reserved_uars = MLX_GET ( &dev_lim, num_rsvd_uars );
arbel->limits.reserved_cqs = arbel->limits.reserved_cqs =
( 1 << MLX_GET ( &dev_lim, log2_rsvd_cqs ) ); ( 1 << MLX_GET ( &dev_lim, log2_rsvd_cqs ) );
arbel->limits.reserved_qps =
( 1 << MLX_GET ( &dev_lim, log2_rsvd_qps ) );
DBG ( "Device limits:\n "); DBG ( "Device limits:\n ");
DBG_HD ( &dev_lim, sizeof ( dev_lim ) ); DBG_HD ( &dev_lim, sizeof ( dev_lim ) );

View File

@ -89,6 +89,8 @@ struct ib_work_queue {
unsigned long 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;
/** Device private data */
void *dev_priv;
}; };
/** An Infiniband Queue Pair */ /** An Infiniband Queue Pair */
@ -99,8 +101,10 @@ struct ib_queue_pair {
struct ib_work_queue send; struct ib_work_queue send;
/** Receive queue */ /** Receive queue */
struct ib_work_queue recv; struct ib_work_queue recv;
/** Device private data */
void *dev_priv;
/** Queue owner private data */ /** Queue owner private data */
void *priv; void *owner_priv;
}; };
/** An Infiniband Completion Queue */ /** An Infiniband Completion Queue */
@ -119,6 +123,8 @@ struct ib_completion_queue {
unsigned long next_idx; unsigned long next_idx;
/** List of work queues completing to this queue */ /** List of work queues completing to this queue */
struct list_head work_queues; struct list_head work_queues;
/** Device private data */
void *dev_priv;
}; };
/** An Infiniband completion */ /** An Infiniband completion */
@ -172,13 +178,11 @@ struct ib_device_operations {
* Create completion queue * Create completion queue
* *
* @v ibdev Infiniband device * @v ibdev Infiniband device
* @v log2_num_cqes Log2 of the number of completion queue entries * @v cq Completion queue
* @ret new_cq New completion queue
* @ret rc Return status code * @ret rc Return status code
*/ */
int ( * create_cq ) ( struct ib_device *ibdev, int ( * create_cq ) ( struct ib_device *ibdev,
unsigned int log2_num_cqes, struct ib_completion_queue *cq );
struct ib_completion_queue **new_cq );
/** /**
* Destroy completion queue * Destroy completion queue
* *
@ -237,8 +241,10 @@ struct ib_device_operations {
/** An Infiniband device */ /** An Infiniband device */
struct ib_device { struct ib_device {
/** Driver private data */ /** Infiniband operations */
void *priv; struct ib_device_operations *op;
/** Device private data */
void *dev_priv;
}; };

View File

@ -17,11 +17,13 @@
*/ */
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <byteswap.h> #include <byteswap.h>
#include <errno.h> #include <errno.h>
#include <assert.h> #include <assert.h>
#include <gpxe/list.h>
#include <gpxe/if_arp.h> #include <gpxe/if_arp.h>
#include <gpxe/netdevice.h> #include <gpxe/netdevice.h>
#include <gpxe/iobuf.h> #include <gpxe/iobuf.h>
@ -33,6 +35,55 @@
* *
*/ */
/**
* Create completion queue
*
* @v ibdev Infiniband device
* @v num_cqes Number of completion queue entries
* @ret cq New completion queue
*/
struct ib_completion_queue * ib_create_cq ( struct ib_device *ibdev,
unsigned int num_cqes ) {
struct ib_completion_queue *cq;
int rc;
DBGC ( ibdev, "IBDEV %p creating completion queue\n", ibdev );
/* Allocate and initialise data structure */
cq = zalloc ( sizeof ( *cq ) );
if ( ! cq )
return NULL;
cq->num_cqes = num_cqes;
INIT_LIST_HEAD ( &cq->work_queues );
/* Perform device-specific initialisation and get CQN */
if ( ( rc = ibdev->op->create_cq ( ibdev, cq ) ) != 0 ) {
DBGC ( ibdev, "IBDEV %p could not initialise CQ: %s\n",
ibdev, strerror ( rc ) );
free ( cq );
return NULL;
}
DBGC ( ibdev, "IBDEV %p created completion queue %#lx\n",
ibdev, cq->cqn );
return cq;
}
/**
* Destroy completion queue
*
* @v ibdev Infiniband device
* @v cq Completion queue
*/
void ib_destroy_cq ( struct ib_device *ibdev,
struct ib_completion_queue *cq ) {
DBGC ( ibdev, "IBDEV %p destroying completion queue %#lx\n",
ibdev, cq->cqn );
assert ( list_empty ( &cq->work_queues ) );
ibdev->op->destroy_cq ( ibdev, cq );
free ( cq );
}
/** /**
* Find work queue belonging to completion queue * Find work queue belonging to completion queue
* *