Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[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.
  • Loading branch information
Michael Brown committed Nov 11, 2008
1 parent d9751ed commit 0de5f7a
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 70 deletions.
15 changes: 4 additions & 11 deletions src/drivers/net/ipoib.c
Expand Up @@ -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;
};
Expand Down Expand Up @@ -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 );
Expand All @@ -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 ) );

Expand All @@ -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--;
}

/**
Expand Down Expand Up @@ -732,7 +727,6 @@ static void ipoib_meta_complete_recv ( struct ib_device *ibdev __unused,
}

done:
ipoib->meta.recv_fill--;
free_iob ( iobuf );
}

Expand All @@ -747,15 +741,14 @@ 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;
if ( ( rc = ib_post_recv ( ibdev, qset->qp, iobuf ) ) != 0 ) {
free_iob ( iobuf );
break;
}
qset->recv_fill++;
}
}

Expand Down
74 changes: 15 additions & 59 deletions src/include/gpxe/infiniband.h
Expand Up @@ -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
Expand Down Expand Up @@ -355,70 +357,24 @@ 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
*
Expand Down
91 changes: 91 additions & 0 deletions src/net/infiniband.c
Expand Up @@ -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
Expand Down

0 comments on commit 0de5f7a

Please sign in to comment.