summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2008-10-03 04:04:21 +0200
committerMichael Brown2008-11-11 06:31:06 +0100
commit0de5f7af6db39ea9173caa0015a63353174d72ce (patch)
tree8f43e82f5401c9fe02175713718302179885e488
parent[infiniband] Flush uncompleted work queue entries at QP teardown (diff)
downloadipxe-0de5f7af6db39ea9173caa0015a63353174d72ce.tar.gz
ipxe-0de5f7af6db39ea9173caa0015a63353174d72ce.tar.xz
ipxe-0de5f7af6db39ea9173caa0015a63353174d72ce.zip
[infiniband] Maintain queue fill level as a property of a work queue
Both queue owners and drivers often need to keep track of the fill level, so let's make it a generic property.
-rw-r--r--src/drivers/net/ipoib.c15
-rw-r--r--src/include/gpxe/infiniband.h74
-rw-r--r--src/net/infiniband.c91
3 files changed, 110 insertions, 70 deletions
diff --git a/src/drivers/net/ipoib.c b/src/drivers/net/ipoib.c
index a56ceb89..55123006 100644
--- a/src/drivers/net/ipoib.c
+++ b/src/drivers/net/ipoib.c
@@ -57,8 +57,6 @@ struct ipoib_queue_set {
struct ib_completion_queue *cq;
/** Queue pair */
struct ib_queue_pair *qp;
- /** Receive work queue fill level */
- unsigned int recv_fill;
/** Receive work queue maximum fill level */
unsigned int recv_max_fill;
};
@@ -565,7 +563,7 @@ static void ipoib_data_complete_recv ( struct ib_device *ibdev __unused,
if ( completion->syndrome ) {
netdev_rx_err ( netdev, iobuf, -EIO );
- goto done;
+ return;
}
iob_put ( iobuf, completion->len );
@@ -574,7 +572,7 @@ static void ipoib_data_complete_recv ( struct ib_device *ibdev __unused,
"contain GRH\n", ipoib );
DBGC_HD ( ipoib, iobuf->data, iob_len ( iobuf ) );
netdev_rx_err ( netdev, iobuf, -EIO );
- goto done;
+ return;
}
iob_pull ( iobuf, sizeof ( struct ib_global_route_header ) );
@@ -583,16 +581,13 @@ static void ipoib_data_complete_recv ( struct ib_device *ibdev __unused,
"contain IPoIB header\n", ipoib );
DBGC_HD ( ipoib, iobuf->data, iob_len ( iobuf ) );
netdev_rx_err ( netdev, iobuf, -EIO );
- goto done;
+ return;
}
ipoib_pshdr = iob_push ( iobuf, sizeof ( *ipoib_pshdr ) );
/* FIXME: fill in a MAC address for the sake of AoE! */
netdev_rx ( netdev, iobuf );
-
- done:
- ipoib->data.recv_fill--;
}
/**
@@ -732,7 +727,6 @@ static void ipoib_meta_complete_recv ( struct ib_device *ibdev __unused,
}
done:
- ipoib->meta.recv_fill--;
free_iob ( iobuf );
}
@@ -747,7 +741,7 @@ static void ipoib_refill_recv ( struct ipoib_device *ipoib,
struct io_buffer *iobuf;
int rc;
- while ( qset->recv_fill < qset->recv_max_fill ) {
+ while ( qset->qp->recv.fill < qset->recv_max_fill ) {
iobuf = alloc_iob ( IPOIB_PKT_LEN );
if ( ! iobuf )
break;
@@ -755,7 +749,6 @@ static void ipoib_refill_recv ( struct ipoib_device *ipoib,
free_iob ( iobuf );
break;
}
- qset->recv_fill++;
}
}
diff --git a/src/include/gpxe/infiniband.h b/src/include/gpxe/infiniband.h
index 82b7a0a8..36adf234 100644
--- a/src/include/gpxe/infiniband.h
+++ b/src/include/gpxe/infiniband.h
@@ -66,6 +66,8 @@ struct ib_work_queue {
struct list_head list;
/** Number of work queue entries */
unsigned int num_wqes;
+ /** Number of occupied work queue entries */
+ unsigned int fill;
/** Next work queue entry index
*
* This is the index of the next entry to be filled (i.e. the
@@ -355,71 +357,25 @@ extern void ib_destroy_qp ( struct ib_device *ibdev,
struct ib_queue_pair *qp );
extern struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
unsigned long qpn, int is_send );
+extern int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct ib_address_vector *av,
+ struct io_buffer *iobuf );
+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 );
+extern void ib_complete_recv ( struct ib_device *ibdev,
+ struct ib_queue_pair *qp,
+ struct ib_completion *completion,
+ struct io_buffer *iobuf );
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 );
extern void ib_link_state_changed ( struct ib_device *ibdev );
/**
- * Post send work queue entry
- *
- * @v ibdev Infiniband device
- * @v qp Queue pair
- * @v av Address vector
- * @v iobuf I/O buffer
- * @ret rc Return status code
- */
-static inline __attribute__ (( always_inline )) int
-ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
- struct ib_address_vector *av, struct io_buffer *iobuf ) {
- return ibdev->op->post_send ( ibdev, qp, av, iobuf );
-}
-
-/**
- * Post receive work queue entry
- *
- * @v ibdev Infiniband device
- * @v qp Queue pair
- * @v iobuf I/O buffer
- * @ret rc Return status code
- */
-static inline __attribute__ (( always_inline )) int
-ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
- struct io_buffer *iobuf ) {
- return ibdev->op->post_recv ( ibdev, qp, iobuf );
-}
-
-/**
- * Complete send work queue entry
- *
- * @v ibdev Infiniband device
- * @v qp Queue pair
- * @v completion Completion
- * @v iobuf I/O buffer
- */
-static inline __attribute__ (( always_inline )) void
-ib_complete_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
- struct ib_completion *completion,
- struct io_buffer *iobuf ) {
- return qp->send.cq->complete_send ( ibdev, qp, completion, iobuf );
-}
-
-/**
- * Complete receive work queue entry
- *
- * @v ibdev Infiniband device
- * @v qp Queue pair
- * @v completion Completion
- * @v iobuf I/O buffer
- */
-static inline __attribute__ (( always_inline )) void
-ib_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
- struct ib_completion *completion,
- struct io_buffer *iobuf ) {
- return qp->recv.cq->complete_recv ( ibdev, qp, completion, iobuf );
-}
-
-/**
* Poll completion queue
*
* @v ibdev Infiniband device
diff --git a/src/net/infiniband.c b/src/net/infiniband.c
index 8437b4ce..2db8a0f4 100644
--- a/src/net/infiniband.c
+++ b/src/net/infiniband.c
@@ -244,6 +244,97 @@ struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
return NULL;
}
+/**
+ * Post send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v av Address vector
+ * @v iobuf I/O buffer
+ * @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 ) {
+ int rc;
+
+ /* Check queue fill level */
+ if ( qp->send.fill >= qp->send.num_wqes ) {
+ DBGC ( ibdev, "IBDEV %p QPN %#lx send queue full\n",
+ ibdev, qp->qpn );
+ return -ENOBUFS;
+ }
+
+ /* Post to hardware */
+ if ( ( rc = ibdev->op->post_send ( ibdev, qp, av, iobuf ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p QPN %#lx could not post send WQE: "
+ "%s\n", ibdev, qp->qpn, strerror ( rc ) );
+ return rc;
+ }
+
+ qp->send.fill++;
+ return 0;
+}
+
+/**
+ * Post receive work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+int ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
+ struct io_buffer *iobuf ) {
+ int rc;
+
+ /* Check queue fill level */
+ if ( qp->recv.fill >= qp->recv.num_wqes ) {
+ DBGC ( ibdev, "IBDEV %p QPN %#lx receive queue full\n",
+ ibdev, qp->qpn );
+ return -ENOBUFS;
+ }
+
+ /* Post to hardware */
+ if ( ( rc = ibdev->op->post_recv ( ibdev, qp, iobuf ) ) != 0 ) {
+ DBGC ( ibdev, "IBDEV %p QPN %#lx could not post receive WQE: "
+ "%s\n", ibdev, qp->qpn, strerror ( rc ) );
+ return rc;
+ }
+
+ qp->recv.fill++;
+ return 0;
+}
+
+/**
+ * Complete send work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v completion Completion
+ * @v iobuf I/O buffer
+ */
+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 );
+ qp->send.fill--;
+}
+
+/**
+ * Complete receive work queue entry
+ *
+ * @v ibdev Infiniband device
+ * @v qp Queue pair
+ * @v completion Completion
+ * @v iobuf I/O buffer
+ */
+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 );
+ qp->recv.fill--;
+}
+
/***************************************************************************
*
* Management datagram operations