static struct io_buffer *static_ipoib_rx_ring[NUM_IPOIB_RCV_WQES];
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 = {
- .qp = {
- .send = {
- .qp = &static_ipoib_qp.qp,
- .is_send = 1,
- .cq = &static_ipoib_send_cq.cq,
- .num_wqes = NUM_IPOIB_SND_WQES,
- .iobufs = static_ipoib_tx_ring,
- .list = LIST_HEAD_INIT (static_ipoib_qp.qp.send.list),
- },
- .recv = {
- .qp = &static_ipoib_qp.qp,
- .is_send = 0,
- .cq = &static_ipoib_recv_cq.cq,
- .num_wqes = NUM_IPOIB_RCV_WQES,
- .iobufs = static_ipoib_rx_ring,
- .list = LIST_HEAD_INIT (static_ipoib_qp.qp.recv.list),
- },
- },
+
+static struct arbel_completion_queue static_arbel_ipoib_send_cq = {
+ .ci_doorbell_idx = IPOIB_SND_CQ_CI_DB_IDX,
+};
+static struct ib_completion_queue static_ipoib_send_cq = {
+ .cqn = 1234, /* Only used for debug messages */
+ .num_cqes = NUM_IPOIB_SND_CQES,
+ .work_queues = LIST_HEAD_INIT ( static_ipoib_send_cq.work_queues ),
+ .dev_priv = &static_arbel_ipoib_send_cq,
+};
+
+static struct arbel_completion_queue static_arbel_ipoib_recv_cq = {
+ .ci_doorbell_idx = IPOIB_RCV_CQ_CI_DB_IDX,
+};
+static struct ib_completion_queue static_ipoib_recv_cq = {
+ .cqn = 2345, /* Only used for debug messages */
+ .num_cqes = NUM_IPOIB_RCV_CQES,
+ .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 = {
.doorbell_idx = IPOIB_SND_QP_DB_IDX,
},
.doorbell_idx = IPOIB_RCV_QP_DB_IDX,
},
};
-static struct arbel_completion_queue static_ipoib_send_cq = {
- .cq = {
- .cqn = 1234, /* Only used for debug messages */
- .num_cqes = NUM_IPOIB_SND_CQES,
- .work_queues = LIST_HEAD_INIT (static_ipoib_send_cq.cq.work_queues),
+static struct ib_queue_pair static_ipoib_qp = {
+ .send = {
+ .qp = &static_ipoib_qp,
+ .is_send = 1,
+ .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,
-};
-static struct arbel_completion_queue static_ipoib_recv_cq = {
- .cq = {
- .cqn = 2345, /* Only used for debug messages */
- .num_cqes = NUM_IPOIB_RCV_CQES,
- .work_queues = LIST_HEAD_INIT (static_ipoib_recv_cq.cq.work_queues),
+ .recv = {
+ .qp = &static_ipoib_qp,
+ .is_send = 0,
+ .cq = &static_ipoib_recv_cq,
+ .num_wqes = NUM_IPOIB_RCV_WQES,
+ .iobufs = static_ipoib_rx_ring,
+ .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 = {
- .priv = &static_arbel,
+ .dev_priv = &static_arbel,
};
};
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;
}
struct ib_queue_pair *qp,
struct ib_completion *completion,
struct io_buffer *iobuf ) {
- struct net_device *netdev = qp->priv;
+ struct net_device *netdev = qp->owner_priv;
DBG ( "Wahey! TX completion\n" );
netdev_tx_complete_err ( netdev, iobuf,
struct ib_queue_pair *qp,
struct ib_completion *completion,
struct io_buffer *iobuf ) {
- struct net_device *netdev = qp->priv;
+ struct net_device *netdev = qp->owner_priv;
struct mlx_nic *mlx = netdev->priv;
DBG ( "Yay! RX completion on %p len %zx:\n", iobuf, completion->len );
break;
DBG ( "Posting RX buffer %p:\n", iobuf );
if ( ( rc = arbel_post_recv ( &static_ibdev,
- &static_ipoib_qp.qp,
+ &static_ipoib_qp,
iobuf ) ) != 0 ) {
free_iob ( iobuf );
break;
}
/* 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 );
- 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 );
- // mlx_poll_cq ( netdev, mlx->rcv_cqh, mlx_rx_complete );
mlx_refill_rx ( netdev );
}
* Create completion queue
*
* @v ibdev Infiniband device
- * @v log2_num_cqes Log2 of the number of completion queue entries
- * @ret new_cq New completion queue
+ * @v cq Completion queue
* @ret rc Return status code
*/
static int arbel_create_cq ( struct ib_device *ibdev,
- unsigned int log2_num_cqes,
- struct ib_completion_queue **new_cq ) {
- struct arbel *arbel = ibdev->priv;
+ struct ib_completion_queue *cq ) {
+ struct arbel *arbel = ibdev->dev_priv;
struct arbel_completion_queue *arbel_cq;
struct arbelprm_completion_queue_context cqctx;
struct arbelprm_cq_ci_db_record *ci_db_rec;
struct arbelprm_cq_arm_db_record *arm_db_rec;
int cqn_offset;
- unsigned int cqn;
- unsigned int num_cqes;
size_t cqe_size;
- unsigned int ci_doorbell_idx;
- unsigned int arm_doorbell_idx;
unsigned int i;
int rc;
rc = cqn_offset;
goto err_cqn_offset;
}
- 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 );
+ cq->cqn = ( arbel->limits.reserved_cqs + cqn_offset );
/* Allocate control structures */
arbel_cq = zalloc ( sizeof ( *arbel_cq ) );
rc = -ENOMEM;
goto err_arbel_cq;
}
- arbel_cq->cq.cqn = cqn;
- arbel_cq->cq.num_cqes = num_cqes;
- INIT_LIST_HEAD ( &arbel_cq->cq.work_queues );
- arbel_cq->doorbell_idx = ci_doorbell_idx;
+ arbel_cq->ci_doorbell_idx = arbel_cq_ci_doorbell_idx ( cqn_offset );
+ arbel_cq->arm_doorbell_idx = arbel_cq_arm_doorbell_idx ( cqn_offset );
/* Allocate completion queue itself */
- num_cqes = ( 1 << log2_num_cqes );
- cqe_size = ( num_cqes * sizeof ( arbel_cq->cqe[0] ) );
+ cqe_size = ( cq->num_cqes * sizeof ( arbel_cq->cqe[0] ) );
arbel_cq->cqe = malloc_dma ( cqe_size, sizeof ( arbel_cq->cqe[0] ) );
if ( ! arbel_cq->cqe ) {
rc = -ENOMEM;
goto err_cqe;
}
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 );
}
barrier();
/* 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_2 ( ci_db_rec, 1,
res, ARBEL_UAR_RES_CQ_CI,
- cq_number, cqn );
- arm_db_rec = &arbel->db_rec[arm_doorbell_idx].cq_arm;
+ cq_number, cq->cqn );
+ arm_db_rec = &arbel->db_rec[arbel_cq->arm_doorbell_idx].cq_arm;
MLX_FILL_1 ( arm_db_rec, 0, counter, 0 );
MLX_FILL_2 ( arm_db_rec, 1,
res, ARBEL_UAR_RES_CQ_ARM,
- cq_number, cqn );
+ cq_number, cq->cqn );
/* Hand queue over to hardware */
memset ( &cqctx, 0, sizeof ( cqctx ) );
MLX_FILL_1 ( &cqctx, 0, st, 0xa /* "Event fired" */ );
MLX_FILL_1 ( &cqctx, 2, start_address_l,
virt_to_bus ( arbel_cq->cqe ) );
+#if 0
MLX_FILL_2 ( &cqctx, 3,
usr_page, arbel->limits.reserved_uars,
log_cq_size, log2_num_cqes );
+#endif
MLX_FILL_1 ( &cqctx, 5, c_eqn, arbel->eqn );
MLX_FILL_1 ( &cqctx, 6, pd, ARBEL_GLOBAL_PD );
MLX_FILL_1 ( &cqctx, 7, l_key, arbel->reserved_lkey );
- MLX_FILL_1 ( &cqctx, 12, cqn, cqn );
- MLX_FILL_1 ( &cqctx, 13, cq_ci_db_record, ci_doorbell_idx );
- MLX_FILL_1 ( &cqctx, 14, cq_state_db_record, arm_doorbell_idx );
- if ( ( rc = arbel_cmd_sw2hw_cq ( arbel, cqn, &cqctx ) ) != 0 ) {
+ MLX_FILL_1 ( &cqctx, 12, cqn, cq->cqn );
+ MLX_FILL_1 ( &cqctx, 13,
+ cq_ci_db_record, arbel_cq->ci_doorbell_idx );
+ 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",
arbel, strerror ( rc ) );
goto err_sw2hw;
}
- *new_cq = &arbel_cq->cq;
+ cq->dev_priv = arbel_cq;
return 0;
err_sw2hw:
*/
static void arbel_destroy_cq ( struct ib_device *ibdev,
struct ib_completion_queue *cq ) {
- struct arbel *arbel = ibdev->priv;
- struct arbel_completion_queue *arbel_cq =
- container_of ( cq, struct arbel_completion_queue, cq );
+ struct arbel *arbel = ibdev->dev_priv;
+ struct arbel_completion_queue *arbel_cq = cq->dev_priv;
struct arbelprm_cq_ci_db_record *ci_db_rec;
struct arbelprm_cq_arm_db_record *arm_db_rec;
int 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
struct ib_queue_pair *qp,
struct ib_address_vector *av,
struct io_buffer *iobuf ) {
- struct arbel *arbel = ibdev->priv;
- struct arbel_queue_pair *arbel_qp
- = container_of ( qp, struct arbel_queue_pair, qp );
+ struct arbel *arbel = ibdev->dev_priv;
+ struct arbel_queue_pair *arbel_qp = qp->dev_priv;
struct ib_work_queue *wq = &qp->send;
struct arbel_send_work_queue *arbel_send_wq = &arbel_qp->send;
struct arbelprm_ud_send_wqe *prev_wqe;
static int arbel_post_recv ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
struct io_buffer *iobuf ) {
- struct arbel *arbel = ibdev->priv;
- struct arbel_queue_pair *arbel_qp
- = container_of ( qp, struct arbel_queue_pair, qp );
+ struct arbel *arbel = ibdev->dev_priv;
+ struct arbel_queue_pair *arbel_qp = qp->dev_priv;
struct ib_work_queue *wq = &qp->recv;
struct arbel_recv_work_queue *arbel_recv_wq = &arbel_qp->recv;
struct arbelprm_recv_wqe *wqe;
union arbelprm_completion_entry *cqe,
ib_completer_t complete_send,
ib_completer_t complete_recv ) {
- struct arbel *arbel = ibdev->priv;
+ struct arbel *arbel = ibdev->dev_priv;
struct ib_completion completion;
struct ib_work_queue *wq;
struct ib_queue_pair *qp;
return -EIO;
}
qp = wq->qp;
- arbel_qp = container_of ( qp, struct arbel_queue_pair, qp );
+ arbel_qp = qp->dev_priv;
/* Identify work queue entry index */
if ( is_send ) {
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
- = container_of ( cq, struct arbel_completion_queue, cq );
+ struct arbel *arbel = ibdev->dev_priv;
+ struct arbel_completion_queue *arbel_cq = cq->dev_priv;
struct arbelprm_cq_ci_db_record *ci_db_rec;
union arbelprm_completion_entry *cqe;
unsigned int cqe_idx_mask;
/* Update completion queue's index */
cq->next_idx++;
/* 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,
counter, ( cq->next_idx & 0xffffffffUL ) );
}
arbel->db_rec = dev_ib_data.uar_context_base;
arbel->reserved_lkey = dev_ib_data.mkey;
arbel->eqn = dev_ib_data.eq.eqn;
- static_ipoib_qp.send.wqe =
+ static_arbel_ipoib_qp.send.wqe =
( ( struct udqp_st * ) qph )->snd_wq;
- static_ipoib_qp.recv.wqe =
+ static_arbel_ipoib_qp.recv.wqe =
( ( 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;
- static_ipoib_recv_cq.cqe =
+ static_arbel_ipoib_recv_cq.cqe =
( ( struct cq_st * ) ib_data.ipoib_rcv_cq )->cq_buf;
- static_ipoib_qp.qp.qpn = ib_get_qpn ( qph );
- static_ipoib_qp.qp.priv = netdev;
- list_add ( &static_ipoib_qp.qp.send.list,
- &static_ipoib_send_cq.cq.work_queues );
- list_add ( &static_ipoib_qp.qp.recv.list,
- &static_ipoib_recv_cq.cq.work_queues );
+ static_ipoib_qp.qpn = ib_get_qpn ( qph );
+ static_ipoib_qp.owner_priv = netdev;
+ list_add ( &static_ipoib_qp.send.list,
+ &static_ipoib_send_cq.work_queues );
+ list_add ( &static_ipoib_qp.recv.list,
+ &static_ipoib_recv_cq.work_queues );
/* Get device limits */
if ( ( rc = arbel_cmd_query_dev_lim ( arbel, &dev_lim ) ) != 0 ) {
arbel->limits.reserved_uars = MLX_GET ( &dev_lim, num_rsvd_uars );
arbel->limits.reserved_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_HD ( &dev_lim, sizeof ( dev_lim ) );