diff options
| author | Michael Brown | 2008-10-03 01:07:52 +0200 |
|---|---|---|
| committer | Michael Brown | 2008-11-11 06:31:06 +0100 |
| commit | d9751edafa08b2ec3779004d4209400b95884cd4 (patch) | |
| tree | 532aaeda86668006aee5fc6994e6f0b773c2a427 /src/include | |
| parent | [ne2k_isa] Restore support for ne2k isa cards (diff) | |
| download | ipxe-d9751edafa08b2ec3779004d4209400b95884cd4.tar.gz ipxe-d9751edafa08b2ec3779004d4209400b95884cd4.tar.xz ipxe-d9751edafa08b2ec3779004d4209400b95884cd4.zip | |
[infiniband] Flush uncompleted work queue entries at QP teardown
Avoid leaking I/O buffers in ib_destroy_qp() by completing any
outstanding work queue entries with a generic error code. This
requires the completion handlers to be available to ib_destroy_qp(),
which is done by making them static configuration parameters of the CQ
(set by ib_create_cq()) rather than being provided on each call to
ib_poll_cq().
This mimics the functionality of netdev_{tx,rx}_flush(). The netdev
flush functions would previously have been catching any I/O buffers
leaked by the IPoIB data queue (though not by the IPoIB metadata
queue).
Diffstat (limited to 'src/include')
| -rw-r--r-- | src/include/gpxe/infiniband.h | 103 |
1 files changed, 70 insertions, 33 deletions
diff --git a/src/include/gpxe/infiniband.h b/src/include/gpxe/infiniband.h index f9e65348e..82b7a0a8b 100644 --- a/src/include/gpxe/infiniband.h +++ b/src/include/gpxe/infiniband.h @@ -101,26 +101,6 @@ enum ib_queue_pair_mods { IB_MODIFY_QKEY = 0x0001, }; -/** An Infiniband Completion Queue */ -struct ib_completion_queue { - /** Completion queue number */ - unsigned long cqn; - /** Number of completion queue entries */ - unsigned int num_cqes; - /** Next completion queue entry index - * - * This is the index of the next entry to be filled (i.e. the - * first empty entry). This value is not bounded by num_wqes; - * users must logical-AND with (num_wqes-1) to generate an - * array index. - */ - unsigned long next_idx; - /** List of work queues completing to this queue */ - struct list_head work_queues; - /** Driver private data */ - void *drv_priv; -}; - /** An Infiniband completion */ struct ib_completion { /** Syndrome @@ -132,6 +112,14 @@ struct ib_completion { size_t len; }; +/** 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, +}; + /** An Infiniband completion handler * * @v ibdev Infiniband device @@ -144,6 +132,30 @@ typedef void ( * ib_completer_t ) ( struct ib_device *ibdev, struct ib_completion *completion, struct io_buffer *iobuf ); +/** An Infiniband Completion Queue */ +struct ib_completion_queue { + /** Completion queue number */ + unsigned long cqn; + /** Number of completion queue entries */ + unsigned int num_cqes; + /** Next completion queue entry index + * + * This is the index of the next entry to be filled (i.e. the + * first empty entry). This value is not bounded by num_wqes; + * users must logical-AND with (num_wqes-1) to generate an + * array index. + */ + 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; + /** Driver private data */ + void *drv_priv; +}; + /** An Infiniband Address Vector */ struct ib_address_vector { /** Destination Queue Pair */ @@ -246,15 +258,12 @@ struct ib_device_operations { * * @v ibdev Infiniband device * @v cq Completion queue - * @v complete_send Send completion handler - * @v complete_recv Receive completion handler * - * The completion handler takes ownership of the I/O buffer. + * The relevant completion handler (specified at completion + * queue creation time) takes ownership of the I/O buffer. */ void ( * poll_cq ) ( struct ib_device *ibdev, - struct ib_completion_queue *cq, - ib_completer_t complete_send, - ib_completer_t complete_recv ); + struct ib_completion_queue *cq ); /** * Poll event queue * @@ -331,8 +340,9 @@ struct ib_device { void *owner_priv; }; -extern struct ib_completion_queue * ib_create_cq ( struct ib_device *ibdev, - unsigned int num_cqes ); +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 ); extern void ib_destroy_cq ( struct ib_device *ibdev, struct ib_completion_queue *cq ); extern struct ib_queue_pair * @@ -380,17 +390,44 @@ ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp, } /** + * 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 * @v cq Completion queue - * @v complete_send Send completion handler - * @v complete_recv Receive completion handler */ static inline __attribute__ (( always_inline )) void -ib_poll_cq ( struct ib_device *ibdev, struct ib_completion_queue *cq, - ib_completer_t complete_send, ib_completer_t complete_recv ) { - ibdev->op->poll_cq ( ibdev, cq, complete_send, complete_recv ); +ib_poll_cq ( struct ib_device *ibdev, struct ib_completion_queue *cq ) { + ibdev->op->poll_cq ( ibdev, cq ); } /** |
