mirror of https://github.com/ipxe/ipxe.git
[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).pull/1/head
parent
dd34500188
commit
d9751edafa
|
@ -1106,15 +1106,11 @@ static int arbel_post_recv ( struct ib_device *ibdev,
|
||||||
* @v ibdev Infiniband device
|
* @v ibdev Infiniband device
|
||||||
* @v cq Completion queue
|
* @v cq Completion queue
|
||||||
* @v cqe Hardware completion queue entry
|
* @v cqe Hardware completion queue entry
|
||||||
* @v complete_send Send completion handler
|
|
||||||
* @v complete_recv Receive completion handler
|
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int arbel_complete ( struct ib_device *ibdev,
|
static int arbel_complete ( struct ib_device *ibdev,
|
||||||
struct ib_completion_queue *cq,
|
struct ib_completion_queue *cq,
|
||||||
union arbelprm_completion_entry *cqe,
|
union arbelprm_completion_entry *cqe ) {
|
||||||
ib_completer_t complete_send,
|
|
||||||
ib_completer_t complete_recv ) {
|
|
||||||
struct arbel *arbel = ib_get_drvdata ( ibdev );
|
struct arbel *arbel = ib_get_drvdata ( ibdev );
|
||||||
struct ib_completion completion;
|
struct ib_completion completion;
|
||||||
struct ib_work_queue *wq;
|
struct ib_work_queue *wq;
|
||||||
|
@ -1124,7 +1120,6 @@ static int arbel_complete ( struct ib_device *ibdev,
|
||||||
struct arbel_recv_work_queue *arbel_recv_wq;
|
struct arbel_recv_work_queue *arbel_recv_wq;
|
||||||
struct arbelprm_recv_wqe *recv_wqe;
|
struct arbelprm_recv_wqe *recv_wqe;
|
||||||
struct io_buffer *iobuf;
|
struct io_buffer *iobuf;
|
||||||
ib_completer_t complete;
|
|
||||||
unsigned int opcode;
|
unsigned int opcode;
|
||||||
unsigned long qpn;
|
unsigned long qpn;
|
||||||
int is_send;
|
int is_send;
|
||||||
|
@ -1201,8 +1196,11 @@ static int arbel_complete ( struct ib_device *ibdev,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pass off to caller's completion handler */
|
/* Pass off to caller's completion handler */
|
||||||
complete = ( is_send ? complete_send : complete_recv );
|
if ( is_send ) {
|
||||||
complete ( ibdev, qp, &completion, iobuf );
|
ib_complete_send ( ibdev, qp, &completion, iobuf );
|
||||||
|
} else {
|
||||||
|
ib_complete_recv ( ibdev, qp, &completion, iobuf );
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1212,13 +1210,9 @@ static int arbel_complete ( struct ib_device *ibdev,
|
||||||
*
|
*
|
||||||
* @v ibdev Infiniband device
|
* @v ibdev Infiniband device
|
||||||
* @v cq Completion queue
|
* @v cq Completion queue
|
||||||
* @v complete_send Send completion handler
|
|
||||||
* @v complete_recv Receive completion handler
|
|
||||||
*/
|
*/
|
||||||
static void arbel_poll_cq ( struct ib_device *ibdev,
|
static void arbel_poll_cq ( struct ib_device *ibdev,
|
||||||
struct ib_completion_queue *cq,
|
struct ib_completion_queue *cq ) {
|
||||||
ib_completer_t complete_send,
|
|
||||||
ib_completer_t complete_recv ) {
|
|
||||||
struct arbel *arbel = ib_get_drvdata ( ibdev );
|
struct arbel *arbel = ib_get_drvdata ( ibdev );
|
||||||
struct arbel_completion_queue *arbel_cq = ib_cq_get_drvdata ( cq );
|
struct arbel_completion_queue *arbel_cq = ib_cq_get_drvdata ( cq );
|
||||||
struct arbelprm_cq_ci_db_record *ci_db_rec;
|
struct arbelprm_cq_ci_db_record *ci_db_rec;
|
||||||
|
@ -1236,8 +1230,7 @@ static void arbel_poll_cq ( struct ib_device *ibdev,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle completion */
|
/* Handle completion */
|
||||||
if ( ( rc = arbel_complete ( ibdev, cq, cqe, complete_send,
|
if ( ( rc = arbel_complete ( ibdev, cq, cqe ) ) != 0 ) {
|
||||||
complete_recv ) ) != 0 ) {
|
|
||||||
DBGC ( arbel, "Arbel %p failed to complete: %s\n",
|
DBGC ( arbel, "Arbel %p failed to complete: %s\n",
|
||||||
arbel, strerror ( rc ) );
|
arbel, strerror ( rc ) );
|
||||||
DBGC_HD ( arbel, cqe, sizeof ( *cqe ) );
|
DBGC_HD ( arbel, cqe, sizeof ( *cqe ) );
|
||||||
|
|
|
@ -1101,22 +1101,17 @@ static int hermon_post_recv ( struct ib_device *ibdev,
|
||||||
* @v ibdev Infiniband device
|
* @v ibdev Infiniband device
|
||||||
* @v cq Completion queue
|
* @v cq Completion queue
|
||||||
* @v cqe Hardware completion queue entry
|
* @v cqe Hardware completion queue entry
|
||||||
* @v complete_send Send completion handler
|
|
||||||
* @v complete_recv Receive completion handler
|
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int hermon_complete ( struct ib_device *ibdev,
|
static int hermon_complete ( struct ib_device *ibdev,
|
||||||
struct ib_completion_queue *cq,
|
struct ib_completion_queue *cq,
|
||||||
union hermonprm_completion_entry *cqe,
|
union hermonprm_completion_entry *cqe ) {
|
||||||
ib_completer_t complete_send,
|
|
||||||
ib_completer_t complete_recv ) {
|
|
||||||
struct hermon *hermon = ib_get_drvdata ( ibdev );
|
struct hermon *hermon = ib_get_drvdata ( ibdev );
|
||||||
struct ib_completion completion;
|
struct ib_completion completion;
|
||||||
struct ib_work_queue *wq;
|
struct ib_work_queue *wq;
|
||||||
struct ib_queue_pair *qp;
|
struct ib_queue_pair *qp;
|
||||||
struct hermon_queue_pair *hermon_qp;
|
struct hermon_queue_pair *hermon_qp;
|
||||||
struct io_buffer *iobuf;
|
struct io_buffer *iobuf;
|
||||||
ib_completer_t complete;
|
|
||||||
unsigned int opcode;
|
unsigned int opcode;
|
||||||
unsigned long qpn;
|
unsigned long qpn;
|
||||||
int is_send;
|
int is_send;
|
||||||
|
@ -1172,8 +1167,11 @@ static int hermon_complete ( struct ib_device *ibdev,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pass off to caller's completion handler */
|
/* Pass off to caller's completion handler */
|
||||||
complete = ( is_send ? complete_send : complete_recv );
|
if ( is_send ) {
|
||||||
complete ( ibdev, qp, &completion, iobuf );
|
ib_complete_send ( ibdev, qp, &completion, iobuf );
|
||||||
|
} else {
|
||||||
|
ib_complete_recv ( ibdev, qp, &completion, iobuf );
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1183,13 +1181,9 @@ static int hermon_complete ( struct ib_device *ibdev,
|
||||||
*
|
*
|
||||||
* @v ibdev Infiniband device
|
* @v ibdev Infiniband device
|
||||||
* @v cq Completion queue
|
* @v cq Completion queue
|
||||||
* @v complete_send Send completion handler
|
|
||||||
* @v complete_recv Receive completion handler
|
|
||||||
*/
|
*/
|
||||||
static void hermon_poll_cq ( struct ib_device *ibdev,
|
static void hermon_poll_cq ( struct ib_device *ibdev,
|
||||||
struct ib_completion_queue *cq,
|
struct ib_completion_queue *cq ) {
|
||||||
ib_completer_t complete_send,
|
|
||||||
ib_completer_t complete_recv ) {
|
|
||||||
struct hermon *hermon = ib_get_drvdata ( ibdev );
|
struct hermon *hermon = ib_get_drvdata ( ibdev );
|
||||||
struct hermon_completion_queue *hermon_cq = ib_cq_get_drvdata ( cq );
|
struct hermon_completion_queue *hermon_cq = ib_cq_get_drvdata ( cq );
|
||||||
union hermonprm_completion_entry *cqe;
|
union hermonprm_completion_entry *cqe;
|
||||||
|
@ -1209,8 +1203,7 @@ static void hermon_poll_cq ( struct ib_device *ibdev,
|
||||||
DBGCP_HD ( hermon, cqe, sizeof ( *cqe ) );
|
DBGCP_HD ( hermon, cqe, sizeof ( *cqe ) );
|
||||||
|
|
||||||
/* Handle completion */
|
/* Handle completion */
|
||||||
if ( ( rc = hermon_complete ( ibdev, cq, cqe, complete_send,
|
if ( ( rc = hermon_complete ( ibdev, cq, cqe ) ) != 0 ) {
|
||||||
complete_recv ) ) != 0 ) {
|
|
||||||
DBGC ( hermon, "Hermon %p failed to complete: %s\n",
|
DBGC ( hermon, "Hermon %p failed to complete: %s\n",
|
||||||
hermon, strerror ( rc ) );
|
hermon, strerror ( rc ) );
|
||||||
DBGC_HD ( hermon, cqe, sizeof ( *cqe ) );
|
DBGC_HD ( hermon, cqe, sizeof ( *cqe ) );
|
||||||
|
|
|
@ -278,13 +278,21 @@ static void ipoib_destroy_qset ( struct ipoib_device *ipoib,
|
||||||
*
|
*
|
||||||
* @v ipoib IPoIB device
|
* @v ipoib IPoIB device
|
||||||
* @v qset Queue set
|
* @v qset Queue set
|
||||||
|
* @v num_cqes Number of completion queue entries
|
||||||
|
* @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
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int ipoib_create_qset ( struct ipoib_device *ipoib,
|
static int ipoib_create_qset ( struct ipoib_device *ipoib,
|
||||||
struct ipoib_queue_set *qset,
|
struct ipoib_queue_set *qset,
|
||||||
unsigned int num_cqes,
|
unsigned int num_cqes,
|
||||||
unsigned int num_send_wqes,
|
unsigned int num_send_wqes,
|
||||||
|
ib_completer_t complete_send,
|
||||||
unsigned int num_recv_wqes,
|
unsigned int num_recv_wqes,
|
||||||
|
ib_completer_t complete_recv,
|
||||||
unsigned long qkey ) {
|
unsigned long qkey ) {
|
||||||
struct ib_device *ibdev = ipoib->ibdev;
|
struct ib_device *ibdev = ipoib->ibdev;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -297,7 +305,8 @@ static int ipoib_create_qset ( struct ipoib_device *ipoib,
|
||||||
qset->recv_max_fill = num_recv_wqes;
|
qset->recv_max_fill = num_recv_wqes;
|
||||||
|
|
||||||
/* Allocate completion queue */
|
/* Allocate completion queue */
|
||||||
qset->cq = ib_create_cq ( ibdev, num_cqes );
|
qset->cq = ib_create_cq ( ibdev, num_cqes, complete_send,
|
||||||
|
complete_recv );
|
||||||
if ( ! qset->cq ) {
|
if ( ! qset->cq ) {
|
||||||
DBGC ( ipoib, "IPoIB %p could not allocate completion queue\n",
|
DBGC ( ipoib, "IPoIB %p could not allocate completion queue\n",
|
||||||
ipoib );
|
ipoib );
|
||||||
|
@ -759,10 +768,8 @@ static void ipoib_poll ( struct net_device *netdev ) {
|
||||||
struct ipoib_device *ipoib = netdev->priv;
|
struct ipoib_device *ipoib = netdev->priv;
|
||||||
struct ib_device *ibdev = ipoib->ibdev;
|
struct ib_device *ibdev = ipoib->ibdev;
|
||||||
|
|
||||||
ib_poll_cq ( ibdev, ipoib->meta.cq, ipoib_meta_complete_send,
|
ib_poll_cq ( ibdev, ipoib->meta.cq );
|
||||||
ipoib_meta_complete_recv );
|
ib_poll_cq ( ibdev, ipoib->data.cq );
|
||||||
ib_poll_cq ( ibdev, ipoib->data.cq, ipoib_data_complete_send,
|
|
||||||
ipoib_data_complete_recv );
|
|
||||||
ipoib_refill_recv ( ipoib, &ipoib->meta );
|
ipoib_refill_recv ( ipoib, &ipoib->meta );
|
||||||
ipoib_refill_recv ( ipoib, &ipoib->data );
|
ipoib_refill_recv ( ipoib, &ipoib->data );
|
||||||
}
|
}
|
||||||
|
@ -847,7 +854,9 @@ static int ipoib_open ( struct net_device *netdev ) {
|
||||||
if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->meta,
|
if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->meta,
|
||||||
IPOIB_META_NUM_CQES,
|
IPOIB_META_NUM_CQES,
|
||||||
IPOIB_META_NUM_SEND_WQES,
|
IPOIB_META_NUM_SEND_WQES,
|
||||||
|
ipoib_meta_complete_send,
|
||||||
IPOIB_META_NUM_RECV_WQES,
|
IPOIB_META_NUM_RECV_WQES,
|
||||||
|
ipoib_meta_complete_recv,
|
||||||
IB_GLOBAL_QKEY ) ) != 0 ) {
|
IB_GLOBAL_QKEY ) ) != 0 ) {
|
||||||
DBGC ( ipoib, "IPoIB %p could not allocate metadata QP: %s\n",
|
DBGC ( ipoib, "IPoIB %p could not allocate metadata QP: %s\n",
|
||||||
ipoib, strerror ( rc ) );
|
ipoib, strerror ( rc ) );
|
||||||
|
@ -858,7 +867,9 @@ static int ipoib_open ( struct net_device *netdev ) {
|
||||||
if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->data,
|
if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->data,
|
||||||
IPOIB_DATA_NUM_CQES,
|
IPOIB_DATA_NUM_CQES,
|
||||||
IPOIB_DATA_NUM_SEND_WQES,
|
IPOIB_DATA_NUM_SEND_WQES,
|
||||||
|
ipoib_data_complete_send,
|
||||||
IPOIB_DATA_NUM_RECV_WQES,
|
IPOIB_DATA_NUM_RECV_WQES,
|
||||||
|
ipoib_data_complete_recv,
|
||||||
IB_GLOBAL_QKEY ) ) != 0 ) {
|
IB_GLOBAL_QKEY ) ) != 0 ) {
|
||||||
DBGC ( ipoib, "IPoIB %p could not allocate data QP: %s\n",
|
DBGC ( ipoib, "IPoIB %p could not allocate data QP: %s\n",
|
||||||
ipoib, strerror ( rc ) );
|
ipoib, strerror ( rc ) );
|
||||||
|
|
|
@ -101,6 +101,37 @@ enum ib_queue_pair_mods {
|
||||||
IB_MODIFY_QKEY = 0x0001,
|
IB_MODIFY_QKEY = 0x0001,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** An Infiniband completion */
|
||||||
|
struct ib_completion {
|
||||||
|
/** Syndrome
|
||||||
|
*
|
||||||
|
* If non-zero, then the completion is in error.
|
||||||
|
*/
|
||||||
|
unsigned int syndrome;
|
||||||
|
/** Length */
|
||||||
|
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
|
||||||
|
* @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 */
|
/** An Infiniband Completion Queue */
|
||||||
struct ib_completion_queue {
|
struct ib_completion_queue {
|
||||||
/** Completion queue number */
|
/** Completion queue number */
|
||||||
|
@ -117,33 +148,14 @@ struct ib_completion_queue {
|
||||||
unsigned long next_idx;
|
unsigned long next_idx;
|
||||||
/** List of work queues completing to this queue */
|
/** List of work queues completing to this queue */
|
||||||
struct list_head work_queues;
|
struct list_head work_queues;
|
||||||
|
/** Send completion handler */
|
||||||
|
ib_completer_t complete_send;
|
||||||
|
/** Receive completion handler */
|
||||||
|
ib_completer_t complete_recv;
|
||||||
/** Driver private data */
|
/** Driver private data */
|
||||||
void *drv_priv;
|
void *drv_priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** An Infiniband completion */
|
|
||||||
struct ib_completion {
|
|
||||||
/** Syndrome
|
|
||||||
*
|
|
||||||
* If non-zero, then the completion is in error.
|
|
||||||
*/
|
|
||||||
unsigned int syndrome;
|
|
||||||
/** Length */
|
|
||||||
size_t len;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 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 Address Vector */
|
/** An Infiniband Address Vector */
|
||||||
struct ib_address_vector {
|
struct ib_address_vector {
|
||||||
/** Destination Queue Pair */
|
/** Destination Queue Pair */
|
||||||
|
@ -246,15 +258,12 @@ struct ib_device_operations {
|
||||||
*
|
*
|
||||||
* @v ibdev Infiniband device
|
* @v ibdev Infiniband device
|
||||||
* @v cq Completion queue
|
* @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,
|
void ( * poll_cq ) ( struct ib_device *ibdev,
|
||||||
struct ib_completion_queue *cq,
|
struct ib_completion_queue *cq );
|
||||||
ib_completer_t complete_send,
|
|
||||||
ib_completer_t complete_recv );
|
|
||||||
/**
|
/**
|
||||||
* Poll event queue
|
* Poll event queue
|
||||||
*
|
*
|
||||||
|
@ -331,8 +340,9 @@ struct ib_device {
|
||||||
void *owner_priv;
|
void *owner_priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct ib_completion_queue * ib_create_cq ( struct ib_device *ibdev,
|
extern struct ib_completion_queue *
|
||||||
unsigned int num_cqes );
|
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,
|
extern void ib_destroy_cq ( struct ib_device *ibdev,
|
||||||
struct ib_completion_queue *cq );
|
struct ib_completion_queue *cq );
|
||||||
extern struct ib_queue_pair *
|
extern struct ib_queue_pair *
|
||||||
|
@ -379,18 +389,45 @@ ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
|
||||||
return ibdev->op->post_recv ( ibdev, qp, 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
|
* Poll completion queue
|
||||||
*
|
*
|
||||||
* @v ibdev Infiniband device
|
* @v ibdev Infiniband device
|
||||||
* @v cq Completion queue
|
* @v cq Completion queue
|
||||||
* @v complete_send Send completion handler
|
|
||||||
* @v complete_recv Receive completion handler
|
|
||||||
*/
|
*/
|
||||||
static inline __attribute__ (( always_inline )) void
|
static inline __attribute__ (( always_inline )) void
|
||||||
ib_poll_cq ( struct ib_device *ibdev, struct ib_completion_queue *cq,
|
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 );
|
||||||
ibdev->op->poll_cq ( ibdev, cq, complete_send, complete_recv );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -46,10 +46,13 @@ struct list_head ib_devices = LIST_HEAD_INIT ( ib_devices );
|
||||||
*
|
*
|
||||||
* @v ibdev Infiniband device
|
* @v ibdev Infiniband device
|
||||||
* @v num_cqes Number of completion queue entries
|
* @v num_cqes Number of completion queue entries
|
||||||
|
* @v complete_send Send completion handler
|
||||||
|
* @v complete_recv Receive completion handler
|
||||||
* @ret cq New completion queue
|
* @ret cq New completion queue
|
||||||
*/
|
*/
|
||||||
struct ib_completion_queue * ib_create_cq ( struct ib_device *ibdev,
|
struct ib_completion_queue *
|
||||||
unsigned int num_cqes ) {
|
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 *cq;
|
struct ib_completion_queue *cq;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -61,6 +64,8 @@ struct ib_completion_queue * ib_create_cq ( struct ib_device *ibdev,
|
||||||
return NULL;
|
return NULL;
|
||||||
cq->num_cqes = num_cqes;
|
cq->num_cqes = num_cqes;
|
||||||
INIT_LIST_HEAD ( &cq->work_queues );
|
INIT_LIST_HEAD ( &cq->work_queues );
|
||||||
|
cq->complete_send = complete_send;
|
||||||
|
cq->complete_recv = complete_recv;
|
||||||
|
|
||||||
/* Perform device-specific initialisation and get CQN */
|
/* Perform device-specific initialisation and get CQN */
|
||||||
if ( ( rc = ibdev->op->create_cq ( ibdev, cq ) ) != 0 ) {
|
if ( ( rc = ibdev->op->create_cq ( ibdev, cq ) ) != 0 ) {
|
||||||
|
@ -190,11 +195,33 @@ int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp,
|
||||||
* @v qp Queue pair
|
* @v qp Queue pair
|
||||||
*/
|
*/
|
||||||
void ib_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
|
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;
|
||||||
|
|
||||||
DBGC ( ibdev, "IBDEV %p destroying QPN %#lx\n",
|
DBGC ( ibdev, "IBDEV %p destroying QPN %#lx\n",
|
||||||
ibdev, qp->qpn );
|
ibdev, qp->qpn );
|
||||||
|
|
||||||
|
/* Perform device-specific destruction */
|
||||||
ibdev->op->destroy_qp ( ibdev, qp );
|
ibdev->op->destroy_qp ( ibdev, 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 );
|
||||||
|
}
|
||||||
|
for ( i = 0 ; i < qp->recv.num_wqes ; i++ ) {
|
||||||
|
if ( ( iobuf = qp->recv.iobufs[i] ) != NULL )
|
||||||
|
ib_complete_recv ( ibdev, qp, &completion, iobuf );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove work queues from completion queue */
|
||||||
list_del ( &qp->send.list );
|
list_del ( &qp->send.list );
|
||||||
list_del ( &qp->recv.list );
|
list_del ( &qp->recv.list );
|
||||||
|
|
||||||
|
/* Free QP */
|
||||||
free ( qp );
|
free ( qp );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue