summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/drivers/infiniband/arbel.c50
-rw-r--r--src/drivers/infiniband/hermon.c46
-rw-r--r--src/drivers/net/ipoib.c109
-rw-r--r--src/include/gpxe/infiniband.h105
-rw-r--r--src/net/infiniband.c38
5 files changed, 172 insertions, 176 deletions
diff --git a/src/drivers/infiniband/arbel.c b/src/drivers/infiniband/arbel.c
index 2649a4ab..8a31ad8b 100644
--- a/src/drivers/infiniband/arbel.c
+++ b/src/drivers/infiniband/arbel.c
@@ -1006,7 +1006,7 @@ static int arbel_post_send ( struct ib_device *ibdev,
ud_address_vector.pd, ARBEL_GLOBAL_PD,
ud_address_vector.port_number, ibdev->port );
MLX_FILL_2 ( &wqe->ud, 1,
- ud_address_vector.rlid, av->dlid,
+ ud_address_vector.rlid, av->lid,
ud_address_vector.g, av->gid_present );
MLX_FILL_2 ( &wqe->ud, 2,
ud_address_vector.max_stat_rate,
@@ -1015,7 +1015,7 @@ static int arbel_post_send ( struct ib_device *ibdev,
MLX_FILL_1 ( &wqe->ud, 3, ud_address_vector.sl, av->sl );
gid = ( av->gid_present ? &av->gid : &arbel_no_gid );
memcpy ( &wqe->ud.u.dwords[4], gid, sizeof ( *gid ) );
- MLX_FILL_1 ( &wqe->ud, 8, destination_qp, av->dest_qp );
+ MLX_FILL_1 ( &wqe->ud, 8, destination_qp, av->qpn );
MLX_FILL_1 ( &wqe->ud, 9, q_key, av->qkey );
MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_len ( iobuf ) );
MLX_FILL_1 ( &wqe->data[0], 1, l_key, arbel->reserved_lkey );
@@ -1112,7 +1112,6 @@ static int arbel_complete ( struct ib_device *ibdev,
struct ib_completion_queue *cq,
union arbelprm_completion_entry *cqe ) {
struct arbel *arbel = ib_get_drvdata ( ibdev );
- struct ib_completion completion;
struct ib_work_queue *wq;
struct ib_queue_pair *qp;
struct arbel_queue_pair *arbel_qp;
@@ -1120,15 +1119,17 @@ static int arbel_complete ( struct ib_device *ibdev,
struct arbel_recv_work_queue *arbel_recv_wq;
struct arbelprm_recv_wqe *recv_wqe;
struct io_buffer *iobuf;
+ struct ib_address_vector av;
+ struct ib_global_route_header *grh;
unsigned int opcode;
unsigned long qpn;
int is_send;
unsigned long wqe_adr;
unsigned int wqe_idx;
+ size_t len;
int rc = 0;
/* Parse completion */
- memset ( &completion, 0, sizeof ( completion ) );
qpn = MLX_GET ( &cqe->normal, my_qpn );
is_send = MLX_GET ( &cqe->normal, s );
wqe_adr = ( MLX_GET ( &cqe->normal, wqe_adr ) << 6 );
@@ -1136,9 +1137,8 @@ static int arbel_complete ( struct ib_device *ibdev,
if ( opcode >= ARBEL_OPCODE_RECV_ERROR ) {
/* "s" field is not valid for error opcodes */
is_send = ( opcode == ARBEL_OPCODE_SEND_ERROR );
- completion.syndrome = MLX_GET ( &cqe->error, syndrome );
- DBGC ( arbel, "Arbel %p CPN %lx syndrome %x vendor %lx\n",
- arbel, cq->cqn, completion.syndrome,
+ DBGC ( arbel, "Arbel %p CPN %lx syndrome %lx vendor %lx\n",
+ arbel, cq->cqn, MLX_GET ( &cqe->error, syndrome ),
MLX_GET ( &cqe->error, vendor_code ) );
rc = -EIO;
/* Don't return immediately; propagate error to completer */
@@ -1176,9 +1176,12 @@ static int arbel_complete ( struct ib_device *ibdev,
}
wq->iobufs[wqe_idx] = NULL;
- /* Fill in length for received packets */
- if ( ! is_send ) {
- completion.len = MLX_GET ( &cqe->normal, byte_cnt );
+ if ( is_send ) {
+ /* Hand off to completion handler */
+ ib_complete_send ( ibdev, qp, iobuf, rc );
+ } else {
+ /* Set received length */
+ len = MLX_GET ( &cqe->normal, byte_cnt );
recv_wqe = &arbel_recv_wq->wqe[wqe_idx].recv;
assert ( MLX_GET ( &recv_wqe->data[0], local_address_l ) ==
virt_to_bus ( iobuf->data ) );
@@ -1187,19 +1190,20 @@ static int arbel_complete ( struct ib_device *ibdev,
MLX_FILL_1 ( &recv_wqe->data[0], 0, byte_count, 0 );
MLX_FILL_1 ( &recv_wqe->data[0], 1,
l_key, ARBEL_INVALID_LKEY );
- if ( completion.len > iob_tailroom ( iobuf ) ) {
- DBGC ( arbel, "Arbel %p CQN %lx QPN %lx IDX %x "
- "overlength received packet length %zd\n",
- arbel, cq->cqn, qpn, wqe_idx, completion.len );
- return -EIO;
- }
- }
-
- /* Pass off to caller's completion handler */
- if ( is_send ) {
- ib_complete_send ( ibdev, qp, &completion, iobuf );
- } else {
- ib_complete_recv ( ibdev, qp, &completion, iobuf );
+ assert ( len <= iob_tailroom ( iobuf ) );
+ iob_put ( iobuf, len );
+ assert ( iob_len ( iobuf ) >= sizeof ( *grh ) );
+ grh = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *grh ) );
+ /* Construct address vector */
+ memset ( &av, 0, sizeof ( av ) );
+ av.qpn = MLX_GET ( &cqe->normal, rqpn );
+ av.lid = MLX_GET ( &cqe->normal, rlid );
+ av.sl = MLX_GET ( &cqe->normal, sl );
+ av.gid_present = MLX_GET ( &cqe->normal, g );
+ memcpy ( &av.gid, &grh->sgid, sizeof ( av.gid ) );
+ /* Hand off to completion handler */
+ ib_complete_recv ( ibdev, qp, &av, iobuf, rc );
}
return rc;
diff --git a/src/drivers/infiniband/hermon.c b/src/drivers/infiniband/hermon.c
index a8907634..db7619ad 100644
--- a/src/drivers/infiniband/hermon.c
+++ b/src/drivers/infiniband/hermon.c
@@ -1015,7 +1015,7 @@ static int hermon_post_send ( struct ib_device *ibdev,
ud_address_vector.pd, HERMON_GLOBAL_PD,
ud_address_vector.port_number, ibdev->port );
MLX_FILL_2 ( &wqe->ud, 1,
- ud_address_vector.rlid, av->dlid,
+ ud_address_vector.rlid, av->lid,
ud_address_vector.g, av->gid_present );
MLX_FILL_1 ( &wqe->ud, 2,
ud_address_vector.max_stat_rate,
@@ -1024,7 +1024,7 @@ static int hermon_post_send ( struct ib_device *ibdev,
MLX_FILL_1 ( &wqe->ud, 3, ud_address_vector.sl, av->sl );
gid = ( av->gid_present ? &av->gid : &hermon_no_gid );
memcpy ( &wqe->ud.u.dwords[4], gid, sizeof ( *gid ) );
- MLX_FILL_1 ( &wqe->ud, 8, destination_qp, av->dest_qp );
+ MLX_FILL_1 ( &wqe->ud, 8, destination_qp, av->qpn );
MLX_FILL_1 ( &wqe->ud, 9, q_key, av->qkey );
MLX_FILL_1 ( &wqe->data[0], 0, byte_count, iob_len ( iobuf ) );
MLX_FILL_1 ( &wqe->data[0], 1, l_key, hermon->reserved_lkey );
@@ -1107,28 +1107,28 @@ static int hermon_complete ( struct ib_device *ibdev,
struct ib_completion_queue *cq,
union hermonprm_completion_entry *cqe ) {
struct hermon *hermon = ib_get_drvdata ( ibdev );
- struct ib_completion completion;
struct ib_work_queue *wq;
struct ib_queue_pair *qp;
struct hermon_queue_pair *hermon_qp;
struct io_buffer *iobuf;
+ struct ib_address_vector av;
+ struct ib_global_route_header *grh;
unsigned int opcode;
unsigned long qpn;
int is_send;
unsigned int wqe_idx;
+ size_t len;
int rc = 0;
/* Parse completion */
- memset ( &completion, 0, sizeof ( completion ) );
qpn = MLX_GET ( &cqe->normal, qpn );
is_send = MLX_GET ( &cqe->normal, s_r );
opcode = MLX_GET ( &cqe->normal, opcode );
if ( opcode >= HERMON_OPCODE_RECV_ERROR ) {
/* "s" field is not valid for error opcodes */
is_send = ( opcode == HERMON_OPCODE_SEND_ERROR );
- completion.syndrome = MLX_GET ( &cqe->error, syndrome );
- DBGC ( hermon, "Hermon %p CQN %lx syndrome %x vendor %lx\n",
- hermon, cq->cqn, completion.syndrome,
+ DBGC ( hermon, "Hermon %p CQN %lx syndrome %lx vendor %lx\n",
+ hermon, cq->cqn, MLX_GET ( &cqe->error, syndrome ),
MLX_GET ( &cqe->error, vendor_error_syndrome ) );
rc = -EIO;
/* Don't return immediately; propagate error to completer */
@@ -1155,22 +1155,26 @@ static int hermon_complete ( struct ib_device *ibdev,
}
wq->iobufs[wqe_idx] = NULL;
- /* Fill in length for received packets */
- if ( ! is_send ) {
- completion.len = MLX_GET ( &cqe->normal, byte_cnt );
- if ( completion.len > iob_tailroom ( iobuf ) ) {
- DBGC ( hermon, "Hermon %p CQN %lx QPN %lx IDX %x "
- "overlength received packet length %zd\n",
- hermon, cq->cqn, qpn, wqe_idx, completion.len );
- return -EIO;
- }
- }
-
- /* Pass off to caller's completion handler */
if ( is_send ) {
- ib_complete_send ( ibdev, qp, &completion, iobuf );
+ /* Hand off to completion handler */
+ ib_complete_send ( ibdev, qp, iobuf, rc );
} else {
- ib_complete_recv ( ibdev, qp, &completion, iobuf );
+ /* Set received length */
+ len = MLX_GET ( &cqe->normal, byte_cnt );
+ assert ( len <= iob_tailroom ( iobuf ) );
+ iob_put ( iobuf, len );
+ assert ( iob_len ( iobuf ) >= sizeof ( *grh ) );
+ grh = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *grh ) );
+ /* Construct address vector */
+ memset ( &av, 0, sizeof ( av ) );
+ av.qpn = MLX_GET ( &cqe->normal, srq_rqpn );
+ av.lid = MLX_GET ( &cqe->normal, slid_smac47_32 );
+ av.sl = MLX_GET ( &cqe->normal, sl );
+ av.gid_present = MLX_GET ( &cqe->normal, g );
+ memcpy ( &av.gid, &grh->sgid, sizeof ( av.gid ) );
+ /* Hand off to completion handler */
+ ib_complete_recv ( ibdev, qp, &av, iobuf, rc );
}
return rc;
diff --git a/src/drivers/net/ipoib.c b/src/drivers/net/ipoib.c
index 55123006..aa68fe38 100644
--- a/src/drivers/net/ipoib.c
+++ b/src/drivers/net/ipoib.c
@@ -277,20 +277,18 @@ static void ipoib_destroy_qset ( struct ipoib_device *ipoib,
* @v ipoib IPoIB device
* @v qset Queue set
* @v num_cqes Number of completion queue entries
+ * @v cq_op Completion queue operations
* @v num_send_wqes Number of send work queue entries
- * @v complete_send Send completion handler
* @v num_recv_wqes Number of receive work queue entries
- * @v complete_recv Receive completion handler
* @v qkey Queue key
* @ret rc Return status code
*/
static int ipoib_create_qset ( struct ipoib_device *ipoib,
struct ipoib_queue_set *qset,
unsigned int num_cqes,
+ struct ib_completion_queue_operations *cq_op,
unsigned int num_send_wqes,
- ib_completer_t complete_send,
unsigned int num_recv_wqes,
- ib_completer_t complete_recv,
unsigned long qkey ) {
struct ib_device *ibdev = ipoib->ibdev;
int rc;
@@ -303,8 +301,7 @@ static int ipoib_create_qset ( struct ipoib_device *ipoib,
qset->recv_max_fill = num_recv_wqes;
/* Allocate completion queue */
- qset->cq = ib_create_cq ( ibdev, num_cqes, complete_send,
- complete_recv );
+ qset->cq = ib_create_cq ( ibdev, num_cqes, cq_op );
if ( ! qset->cq ) {
DBGC ( ipoib, "IPoIB %p could not allocate completion queue\n",
ipoib );
@@ -391,8 +388,8 @@ static int ipoib_get_path_record ( struct ipoib_device *ipoib,
/* Construct address vector */
memset ( &av, 0, sizeof ( av ) );
- av.dlid = ibdev->sm_lid;
- av.dest_qp = IB_SA_QPN;
+ av.lid = ibdev->sm_lid;
+ av.qpn = IB_SA_QPN;
av.qkey = IB_GLOBAL_QKEY;
/* Post send request */
@@ -451,8 +448,8 @@ static int ipoib_mc_member_record ( struct ipoib_device *ipoib,
/* Construct address vector */
memset ( &av, 0, sizeof ( av ) );
- av.dlid = ibdev->sm_lid;
- av.dest_qp = IB_SA_QPN;
+ av.lid = ibdev->sm_lid;
+ av.qpn = IB_SA_QPN;
av.qkey = IB_GLOBAL_QKEY;
/* Post send request */
@@ -503,8 +500,8 @@ static int ipoib_transmit ( struct net_device *netdev,
av.gid_present = 1;
if ( ipoib_pshdr->peer.qpn == htonl ( IPOIB_BROADCAST_QPN ) ) {
/* Broadcast address */
- av.dest_qp = IB_BROADCAST_QPN;
- av.dlid = ipoib->broadcast_lid;
+ av.qpn = IB_BROADCAST_QPN;
+ av.lid = ipoib->broadcast_lid;
gid = &ipoib->broadcast_gid;
} else {
/* Unicast - look in path cache */
@@ -516,8 +513,8 @@ static int ipoib_transmit ( struct net_device *netdev,
netdev_tx_complete ( netdev, iobuf );
return rc;
}
- av.dest_qp = ntohl ( ipoib_pshdr->peer.qpn );
- av.dlid = path->dlid;
+ av.qpn = ntohl ( ipoib_pshdr->peer.qpn );
+ av.lid = path->dlid;
av.rate = path->rate;
av.sl = path->sl;
gid = &ipoib_pshdr->peer.gid;
@@ -532,17 +529,15 @@ static int ipoib_transmit ( struct net_device *netdev,
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v completion Completion
* @v iobuf I/O buffer
+ * @v rc Completion status code
*/
static void ipoib_data_complete_send ( struct ib_device *ibdev __unused,
struct ib_queue_pair *qp,
- struct ib_completion *completion,
- struct io_buffer *iobuf ) {
+ struct io_buffer *iobuf, int rc ) {
struct net_device *netdev = ib_qp_get_ownerdata ( qp );
- netdev_tx_complete_err ( netdev, iobuf,
- ( completion->syndrome ? -EIO : 0 ) );
+ netdev_tx_complete_err ( netdev, iobuf, rc );
}
/**
@@ -550,32 +545,23 @@ static void ipoib_data_complete_send ( struct ib_device *ibdev __unused,
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v completion Completion
+ * @v av Address vector, or NULL
* @v iobuf I/O buffer
+ * @v rc Completion status code
*/
static void ipoib_data_complete_recv ( struct ib_device *ibdev __unused,
struct ib_queue_pair *qp,
- struct ib_completion *completion,
- struct io_buffer *iobuf ) {
+ struct ib_address_vector *av __unused,
+ struct io_buffer *iobuf, int rc ) {
struct net_device *netdev = ib_qp_get_ownerdata ( qp );
struct ipoib_device *ipoib = netdev->priv;
struct ipoib_pseudo_hdr *ipoib_pshdr;
- if ( completion->syndrome ) {
- netdev_rx_err ( netdev, iobuf, -EIO );
+ if ( rc != 0 ) {
+ netdev_rx_err ( netdev, iobuf, rc );
return;
}
- iob_put ( iobuf, completion->len );
- if ( iob_len ( iobuf ) < sizeof ( struct ib_global_route_header ) ) {
- DBGC ( ipoib, "IPoIB %p received data packet too short to "
- "contain GRH\n", ipoib );
- DBGC_HD ( ipoib, iobuf->data, iob_len ( iobuf ) );
- netdev_rx_err ( netdev, iobuf, -EIO );
- return;
- }
- iob_pull ( iobuf, sizeof ( struct ib_global_route_header ) );
-
if ( iob_len ( iobuf ) < sizeof ( struct ipoib_real_hdr ) ) {
DBGC ( ipoib, "IPoIB %p received data packet too short to "
"contain IPoIB header\n", ipoib );
@@ -590,24 +576,29 @@ static void ipoib_data_complete_recv ( struct ib_device *ibdev __unused,
netdev_rx ( netdev, iobuf );
}
+/** IPoIB data completion operations */
+static struct ib_completion_queue_operations ipoib_data_cq_op = {
+ .complete_send = ipoib_data_complete_send,
+ .complete_recv = ipoib_data_complete_recv,
+};
+
/**
* Handle IPoIB metadata send completion
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v completion Completion
* @v iobuf I/O buffer
+ * @v rc Completion status code
*/
static void ipoib_meta_complete_send ( struct ib_device *ibdev __unused,
struct ib_queue_pair *qp,
- struct ib_completion *completion,
- struct io_buffer *iobuf ) {
+ struct io_buffer *iobuf, int rc ) {
struct net_device *netdev = ib_qp_get_ownerdata ( qp );
struct ipoib_device *ipoib = netdev->priv;
- if ( completion->syndrome ) {
- DBGC ( ipoib, "IPoIB %p metadata TX completion error %x\n",
- ipoib, completion->syndrome );
+ if ( rc != 0 ) {
+ DBGC ( ipoib, "IPoIB %p metadata TX completion error: %s\n",
+ ipoib, strerror ( rc ) );
}
free_iob ( iobuf );
}
@@ -673,31 +664,25 @@ static void ipoib_recv_mc_member_record ( struct ipoib_device *ipoib,
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v completion Completion
+ * @v av Address vector, or NULL
* @v iobuf I/O buffer
+ * @v rc Completion status code
*/
-static void ipoib_meta_complete_recv ( struct ib_device *ibdev __unused,
- struct ib_queue_pair *qp,
- struct ib_completion *completion,
- struct io_buffer *iobuf ) {
+static void
+ipoib_meta_complete_recv ( struct ib_device *ibdev __unused,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av __unused,
+ struct io_buffer *iobuf, int rc ) {
struct net_device *netdev = ib_qp_get_ownerdata ( qp );
struct ipoib_device *ipoib = netdev->priv;
union ib_mad *mad;
- if ( completion->syndrome ) {
- DBGC ( ipoib, "IPoIB %p metadata RX completion error %x\n",
- ipoib, completion->syndrome );
+ if ( rc != 0 ) {
+ DBGC ( ipoib, "IPoIB %p metadata RX completion error: %s\n",
+ ipoib, strerror ( rc ) );
goto done;
}
- iob_put ( iobuf, completion->len );
- if ( iob_len ( iobuf ) < sizeof ( struct ib_global_route_header ) ) {
- DBGC ( ipoib, "IPoIB %p received metadata packet too short "
- "to contain GRH\n", ipoib );
- DBGC_HD ( ipoib, iobuf->data, iob_len ( iobuf ) );
- goto done;
- }
- iob_pull ( iobuf, sizeof ( struct ib_global_route_header ) );
if ( iob_len ( iobuf ) < sizeof ( *mad ) ) {
DBGC ( ipoib, "IPoIB %p received metadata packet too short "
"to contain reply\n", ipoib );
@@ -730,6 +715,12 @@ static void ipoib_meta_complete_recv ( struct ib_device *ibdev __unused,
free_iob ( iobuf );
}
+/** IPoIB metadata completion operations */
+static struct ib_completion_queue_operations ipoib_meta_cq_op = {
+ .complete_send = ipoib_meta_complete_send,
+ .complete_recv = ipoib_meta_complete_recv,
+};
+
/**
* Refill IPoIB receive ring
*
@@ -846,10 +837,9 @@ static int ipoib_open ( struct net_device *netdev ) {
/* Allocate metadata queue set */
if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->meta,
IPOIB_META_NUM_CQES,
+ &ipoib_meta_cq_op,
IPOIB_META_NUM_SEND_WQES,
- ipoib_meta_complete_send,
IPOIB_META_NUM_RECV_WQES,
- ipoib_meta_complete_recv,
IB_GLOBAL_QKEY ) ) != 0 ) {
DBGC ( ipoib, "IPoIB %p could not allocate metadata QP: %s\n",
ipoib, strerror ( rc ) );
@@ -859,10 +849,9 @@ static int ipoib_open ( struct net_device *netdev ) {
/* Allocate data queue set */
if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->data,
IPOIB_DATA_NUM_CQES,
+ &ipoib_data_cq_op,
IPOIB_DATA_NUM_SEND_WQES,
- ipoib_data_complete_send,
IPOIB_DATA_NUM_RECV_WQES,
- ipoib_data_complete_recv,
IB_GLOBAL_QKEY ) ) != 0 ) {
DBGC ( ipoib, "IPoIB %p could not allocate data QP: %s\n",
ipoib, strerror ( rc ) );
diff --git a/src/include/gpxe/infiniband.h b/src/include/gpxe/infiniband.h
index 36adf234..ed0d1a66 100644
--- a/src/include/gpxe/infiniband.h
+++ b/src/include/gpxe/infiniband.h
@@ -52,6 +52,7 @@ struct ib_global_route_header {
struct ib_device;
struct ib_queue_pair;
+struct ib_address_vector;
struct ib_completion_queue;
/** An Infiniband Work Queue */
@@ -103,37 +104,58 @@ enum ib_queue_pair_mods {
IB_MODIFY_QKEY = 0x0001,
};
-/** An Infiniband completion */
-struct ib_completion {
- /** Syndrome
+/** An Infiniband Address Vector */
+struct ib_address_vector {
+ /** Queue Pair Number */
+ unsigned long qpn;
+ /** Queue key
*
- * If non-zero, then the completion is in error.
+ * Not specified for received packets.
*/
- unsigned int syndrome;
- /** Length */
- size_t len;
+ unsigned long qkey;
+ /** Local ID */
+ unsigned int lid;
+ /** Rate
+ *
+ * Not specified for received packets.
+ */
+ unsigned int rate;
+ /** Service level */
+ unsigned int sl;
+ /** GID is present */
+ unsigned int gid_present;
+ /** GID, if present */
+ struct ib_gid gid;
};
-/** Infiniband completion syndromes */
-enum ib_syndrome {
- IB_SYN_NONE = 0,
- IB_SYN_LOCAL_LENGTH = 1,
- IB_SYN_LOCAL_QP = 2,
- IB_SYN_LOCAL_PROT = 4,
+/** Infiniband completion queue operations */
+struct ib_completion_queue_operations {
+ /**
+ * Complete Send WQE
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+ void ( * complete_send ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct io_buffer *iobuf, int rc );
+ /**
+ * Complete Receive WQE
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector, or NULL
+ * @v iobuf I/O buffer
+ * @v rc Completion status code
+ */
+ void ( * complete_recv ) ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf, int rc );
};
-/** An Infiniband completion handler
- *
- * @v ibdev Infiniband device
- * @v qp Queue pair
- * @v completion Completion
- * @v iobuf I/O buffer
- */
-typedef void ( * ib_completer_t ) ( struct ib_device *ibdev,
- struct ib_queue_pair *qp,
- struct ib_completion *completion,
- struct io_buffer *iobuf );
-
/** An Infiniband Completion Queue */
struct ib_completion_queue {
/** Completion queue number */
@@ -150,32 +172,12 @@ struct ib_completion_queue {
unsigned long next_idx;
/** List of work queues completing to this queue */
struct list_head work_queues;
- /** Send completion handler */
- ib_completer_t complete_send;
- /** Receive completion handler */
- ib_completer_t complete_recv;
+ /** Completion queue operations */
+ struct ib_completion_queue_operations *op;
/** Driver private data */
void *drv_priv;
};
-/** An Infiniband Address Vector */
-struct ib_address_vector {
- /** Destination Queue Pair */
- unsigned int dest_qp;
- /** Queue key */
- unsigned long qkey;
- /** Destination Local ID */
- unsigned int dlid;
- /** Rate */
- unsigned int rate;
- /** Service level */
- unsigned int sl;
- /** GID is present */
- unsigned int gid_present;
- /** GID */
- struct ib_gid gid;
-};
-
struct ib_mad_hdr;
/**
@@ -344,7 +346,7 @@ struct ib_device {
extern struct ib_completion_queue *
ib_create_cq ( struct ib_device *ibdev, unsigned int num_cqes,
- ib_completer_t complete_send, ib_completer_t complete_recv );
+ struct ib_completion_queue_operations *op );
extern void ib_destroy_cq ( struct ib_device *ibdev,
struct ib_completion_queue *cq );
extern struct ib_queue_pair *
@@ -364,12 +366,11 @@ extern int ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
struct io_buffer *iobuf );
extern void ib_complete_send ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
- struct ib_completion *completion,
- struct io_buffer *iobuf );
+ struct io_buffer *iobuf, int rc );
extern void ib_complete_recv ( struct ib_device *ibdev,
struct ib_queue_pair *qp,
- struct ib_completion *completion,
- struct io_buffer *iobuf );
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf, int rc );
extern struct ib_device * alloc_ibdev ( size_t priv_size );
extern int register_ibdev ( struct ib_device *ibdev );
extern void unregister_ibdev ( struct ib_device *ibdev );
diff --git a/src/net/infiniband.c b/src/net/infiniband.c
index 2db8a0f4..ba7842cf 100644
--- a/src/net/infiniband.c
+++ b/src/net/infiniband.c
@@ -46,13 +46,12 @@ struct list_head ib_devices = LIST_HEAD_INIT ( ib_devices );
*
* @v ibdev Infiniband device
* @v num_cqes Number of completion queue entries
- * @v complete_send Send completion handler
- * @v complete_recv Receive completion handler
+ * @v op Completion queue operations
* @ret cq New completion queue
*/
struct ib_completion_queue *
ib_create_cq ( struct ib_device *ibdev, unsigned int num_cqes,
- ib_completer_t complete_send, ib_completer_t complete_recv ) {
+ struct ib_completion_queue_operations *op ) {
struct ib_completion_queue *cq;
int rc;
@@ -64,8 +63,7 @@ ib_create_cq ( struct ib_device *ibdev, unsigned int num_cqes,
return NULL;
cq->num_cqes = num_cqes;
INIT_LIST_HEAD ( &cq->work_queues );
- cq->complete_send = complete_send;
- cq->complete_recv = complete_recv;
+ cq->op = op;
/* Perform device-specific initialisation and get CQN */
if ( ( rc = ibdev->op->create_cq ( ibdev, cq ) ) != 0 ) {
@@ -195,9 +193,6 @@ int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp,
* @v qp Queue pair
*/
void ib_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
- struct ib_completion completion = {
- .syndrome = IB_SYN_LOCAL_QP,
- };
struct io_buffer *iobuf;
unsigned int i;
@@ -210,11 +205,13 @@ void ib_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
/* Complete any remaining I/O buffers with errors */
for ( i = 0 ; i < qp->send.num_wqes ; i++ ) {
if ( ( iobuf = qp->send.iobufs[i] ) != NULL )
- ib_complete_send ( ibdev, qp, &completion, iobuf );
+ ib_complete_send ( ibdev, qp, iobuf, -ECANCELED );
}
for ( i = 0 ; i < qp->recv.num_wqes ; i++ ) {
- if ( ( iobuf = qp->recv.iobufs[i] ) != NULL )
- ib_complete_recv ( ibdev, qp, &completion, iobuf );
+ if ( ( iobuf = qp->recv.iobufs[i] ) != NULL ) {
+ ib_complete_recv ( ibdev, qp, NULL, iobuf,
+ -ECANCELED );
+ }
}
/* Remove work queues from completion queue */
@@ -254,7 +251,8 @@ struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
* @ret rc Return status code
*/
int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
- struct ib_address_vector *av, struct io_buffer *iobuf ) {
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf ) {
int rc;
/* Check queue fill level */
@@ -310,13 +308,12 @@ int ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v completion Completion
* @v iobuf I/O buffer
+ * @v rc Completion status code
*/
void ib_complete_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
- struct ib_completion *completion,
- struct io_buffer *iobuf ) {
- qp->send.cq->complete_send ( ibdev, qp, completion, iobuf );
+ struct io_buffer *iobuf, int rc ) {
+ qp->send.cq->op->complete_send ( ibdev, qp, iobuf, rc );
qp->send.fill--;
}
@@ -325,13 +322,14 @@ void ib_complete_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
*
* @v ibdev Infiniband device
* @v qp Queue pair
- * @v completion Completion
+ * @v av Address vector
* @v iobuf I/O buffer
+ * @v rc Completion status code
*/
void ib_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
- struct ib_completion *completion,
- struct io_buffer *iobuf ) {
- qp->recv.cq->complete_recv ( ibdev, qp, completion, iobuf );
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf, int rc ) {
+ qp->recv.cq->op->complete_recv ( ibdev, qp, av, iobuf, rc );
qp->recv.fill--;
}