Browse Source

[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).
tags/v0.9.6
Michael Brown 16 years ago
parent
commit
d9751edafa

+ 8
- 15
src/drivers/infiniband/arbel.c View File

1106
  * @v ibdev		Infiniband device
1106
  * @v ibdev		Infiniband device
1107
  * @v cq		Completion queue
1107
  * @v cq		Completion queue
1108
  * @v cqe		Hardware completion queue entry
1108
  * @v cqe		Hardware completion queue entry
1109
- * @v complete_send	Send completion handler
1110
- * @v complete_recv	Receive completion handler
1111
  * @ret rc		Return status code
1109
  * @ret rc		Return status code
1112
  */
1110
  */
1113
 static int arbel_complete ( struct ib_device *ibdev,
1111
 static int arbel_complete ( struct ib_device *ibdev,
1114
 			    struct ib_completion_queue *cq,
1112
 			    struct ib_completion_queue *cq,
1115
-			    union arbelprm_completion_entry *cqe,
1116
-			    ib_completer_t complete_send,
1117
-			    ib_completer_t complete_recv ) {
1113
+			    union arbelprm_completion_entry *cqe ) {
1118
 	struct arbel *arbel = ib_get_drvdata ( ibdev );
1114
 	struct arbel *arbel = ib_get_drvdata ( ibdev );
1119
 	struct ib_completion completion;
1115
 	struct ib_completion completion;
1120
 	struct ib_work_queue *wq;
1116
 	struct ib_work_queue *wq;
1124
 	struct arbel_recv_work_queue *arbel_recv_wq;
1120
 	struct arbel_recv_work_queue *arbel_recv_wq;
1125
 	struct arbelprm_recv_wqe *recv_wqe;
1121
 	struct arbelprm_recv_wqe *recv_wqe;
1126
 	struct io_buffer *iobuf;
1122
 	struct io_buffer *iobuf;
1127
-	ib_completer_t complete;
1128
 	unsigned int opcode;
1123
 	unsigned int opcode;
1129
 	unsigned long qpn;
1124
 	unsigned long qpn;
1130
 	int is_send;
1125
 	int is_send;
1201
 	}
1196
 	}
1202
 
1197
 
1203
 	/* Pass off to caller's completion handler */
1198
 	/* Pass off to caller's completion handler */
1204
-	complete = ( is_send ? complete_send : complete_recv );
1205
-	complete ( ibdev, qp, &completion, iobuf );
1199
+	if ( is_send ) {
1200
+		ib_complete_send ( ibdev, qp, &completion, iobuf );
1201
+	} else {
1202
+		ib_complete_recv ( ibdev, qp, &completion, iobuf );
1203
+	}
1206
 
1204
 
1207
 	return rc;
1205
 	return rc;
1208
 }			     
1206
 }			     
1212
  *
1210
  *
1213
  * @v ibdev		Infiniband device
1211
  * @v ibdev		Infiniband device
1214
  * @v cq		Completion queue
1212
  * @v cq		Completion queue
1215
- * @v complete_send	Send completion handler
1216
- * @v complete_recv	Receive completion handler
1217
  */
1213
  */
1218
 static void arbel_poll_cq ( struct ib_device *ibdev,
1214
 static void arbel_poll_cq ( struct ib_device *ibdev,
1219
-			    struct ib_completion_queue *cq,
1220
-			    ib_completer_t complete_send,
1221
-			    ib_completer_t complete_recv ) {
1215
+			    struct ib_completion_queue *cq ) {
1222
 	struct arbel *arbel = ib_get_drvdata ( ibdev );
1216
 	struct arbel *arbel = ib_get_drvdata ( ibdev );
1223
 	struct arbel_completion_queue *arbel_cq = ib_cq_get_drvdata ( cq );
1217
 	struct arbel_completion_queue *arbel_cq = ib_cq_get_drvdata ( cq );
1224
 	struct arbelprm_cq_ci_db_record *ci_db_rec;
1218
 	struct arbelprm_cq_ci_db_record *ci_db_rec;
1236
 		}
1230
 		}
1237
 
1231
 
1238
 		/* Handle completion */
1232
 		/* Handle completion */
1239
-		if ( ( rc = arbel_complete ( ibdev, cq, cqe, complete_send,
1240
-					     complete_recv ) ) != 0 ) {
1233
+		if ( ( rc = arbel_complete ( ibdev, cq, cqe ) ) != 0 ) {
1241
 			DBGC ( arbel, "Arbel %p failed to complete: %s\n",
1234
 			DBGC ( arbel, "Arbel %p failed to complete: %s\n",
1242
 			       arbel, strerror ( rc ) );
1235
 			       arbel, strerror ( rc ) );
1243
 			DBGC_HD ( arbel, cqe, sizeof ( *cqe ) );
1236
 			DBGC_HD ( arbel, cqe, sizeof ( *cqe ) );

+ 8
- 15
src/drivers/infiniband/hermon.c View File

1101
  * @v ibdev		Infiniband device
1101
  * @v ibdev		Infiniband device
1102
  * @v cq		Completion queue
1102
  * @v cq		Completion queue
1103
  * @v cqe		Hardware completion queue entry
1103
  * @v cqe		Hardware completion queue entry
1104
- * @v complete_send	Send completion handler
1105
- * @v complete_recv	Receive completion handler
1106
  * @ret rc		Return status code
1104
  * @ret rc		Return status code
1107
  */
1105
  */
1108
 static int hermon_complete ( struct ib_device *ibdev,
1106
 static int hermon_complete ( struct ib_device *ibdev,
1109
 			     struct ib_completion_queue *cq,
1107
 			     struct ib_completion_queue *cq,
1110
-			     union hermonprm_completion_entry *cqe,
1111
-			     ib_completer_t complete_send,
1112
-			     ib_completer_t complete_recv ) {
1108
+			     union hermonprm_completion_entry *cqe ) {
1113
 	struct hermon *hermon = ib_get_drvdata ( ibdev );
1109
 	struct hermon *hermon = ib_get_drvdata ( ibdev );
1114
 	struct ib_completion completion;
1110
 	struct ib_completion completion;
1115
 	struct ib_work_queue *wq;
1111
 	struct ib_work_queue *wq;
1116
 	struct ib_queue_pair *qp;
1112
 	struct ib_queue_pair *qp;
1117
 	struct hermon_queue_pair *hermon_qp;
1113
 	struct hermon_queue_pair *hermon_qp;
1118
 	struct io_buffer *iobuf;
1114
 	struct io_buffer *iobuf;
1119
-	ib_completer_t complete;
1120
 	unsigned int opcode;
1115
 	unsigned int opcode;
1121
 	unsigned long qpn;
1116
 	unsigned long qpn;
1122
 	int is_send;
1117
 	int is_send;
1172
 	}
1167
 	}
1173
 
1168
 
1174
 	/* Pass off to caller's completion handler */
1169
 	/* Pass off to caller's completion handler */
1175
-	complete = ( is_send ? complete_send : complete_recv );
1176
-	complete ( ibdev, qp, &completion, iobuf );
1170
+	if ( is_send ) {
1171
+		ib_complete_send ( ibdev, qp, &completion, iobuf );
1172
+	} else {
1173
+		ib_complete_recv ( ibdev, qp, &completion, iobuf );
1174
+	}
1177
 
1175
 
1178
 	return rc;
1176
 	return rc;
1179
 }
1177
 }
1183
  *
1181
  *
1184
  * @v ibdev		Infiniband device
1182
  * @v ibdev		Infiniband device
1185
  * @v cq		Completion queue
1183
  * @v cq		Completion queue
1186
- * @v complete_send	Send completion handler
1187
- * @v complete_recv	Receive completion handler
1188
  */
1184
  */
1189
 static void hermon_poll_cq ( struct ib_device *ibdev,
1185
 static void hermon_poll_cq ( struct ib_device *ibdev,
1190
-			     struct ib_completion_queue *cq,
1191
-			     ib_completer_t complete_send,
1192
-			     ib_completer_t complete_recv ) {
1186
+			     struct ib_completion_queue *cq ) {
1193
 	struct hermon *hermon = ib_get_drvdata ( ibdev );
1187
 	struct hermon *hermon = ib_get_drvdata ( ibdev );
1194
 	struct hermon_completion_queue *hermon_cq = ib_cq_get_drvdata ( cq );
1188
 	struct hermon_completion_queue *hermon_cq = ib_cq_get_drvdata ( cq );
1195
 	union hermonprm_completion_entry *cqe;
1189
 	union hermonprm_completion_entry *cqe;
1209
 		DBGCP_HD ( hermon, cqe, sizeof ( *cqe ) );
1203
 		DBGCP_HD ( hermon, cqe, sizeof ( *cqe ) );
1210
 
1204
 
1211
 		/* Handle completion */
1205
 		/* Handle completion */
1212
-		if ( ( rc = hermon_complete ( ibdev, cq, cqe, complete_send,
1213
-					      complete_recv ) ) != 0 ) {
1206
+		if ( ( rc = hermon_complete ( ibdev, cq, cqe ) ) != 0 ) {
1214
 			DBGC ( hermon, "Hermon %p failed to complete: %s\n",
1207
 			DBGC ( hermon, "Hermon %p failed to complete: %s\n",
1215
 			       hermon, strerror ( rc ) );
1208
 			       hermon, strerror ( rc ) );
1216
 			DBGC_HD ( hermon, cqe, sizeof ( *cqe ) );
1209
 			DBGC_HD ( hermon, cqe, sizeof ( *cqe ) );

+ 16
- 5
src/drivers/net/ipoib.c View File

278
  *
278
  *
279
  * @v ipoib		IPoIB device
279
  * @v ipoib		IPoIB device
280
  * @v qset		Queue set
280
  * @v qset		Queue set
281
+ * @v num_cqes		Number of completion queue entries
282
+ * @v num_send_wqes	Number of send work queue entries
283
+ * @v complete_send	Send completion handler
284
+ * @v num_recv_wqes	Number of receive work queue entries
285
+ * @v complete_recv	Receive completion handler
286
+ * @v qkey		Queue key
281
  * @ret rc		Return status code
287
  * @ret rc		Return status code
282
  */
288
  */
283
 static int ipoib_create_qset ( struct ipoib_device *ipoib,
289
 static int ipoib_create_qset ( struct ipoib_device *ipoib,
284
 			       struct ipoib_queue_set *qset,
290
 			       struct ipoib_queue_set *qset,
285
 			       unsigned int num_cqes,
291
 			       unsigned int num_cqes,
286
 			       unsigned int num_send_wqes,
292
 			       unsigned int num_send_wqes,
293
+			       ib_completer_t complete_send,
287
 			       unsigned int num_recv_wqes,
294
 			       unsigned int num_recv_wqes,
295
+			       ib_completer_t complete_recv,
288
 			       unsigned long qkey ) {
296
 			       unsigned long qkey ) {
289
 	struct ib_device *ibdev = ipoib->ibdev;
297
 	struct ib_device *ibdev = ipoib->ibdev;
290
 	int rc;
298
 	int rc;
297
 	qset->recv_max_fill = num_recv_wqes;
305
 	qset->recv_max_fill = num_recv_wqes;
298
 
306
 
299
 	/* Allocate completion queue */
307
 	/* Allocate completion queue */
300
-	qset->cq = ib_create_cq ( ibdev, num_cqes );
308
+	qset->cq = ib_create_cq ( ibdev, num_cqes, complete_send,
309
+				  complete_recv );
301
 	if ( ! qset->cq ) {
310
 	if ( ! qset->cq ) {
302
 		DBGC ( ipoib, "IPoIB %p could not allocate completion queue\n",
311
 		DBGC ( ipoib, "IPoIB %p could not allocate completion queue\n",
303
 		       ipoib );
312
 		       ipoib );
759
 	struct ipoib_device *ipoib = netdev->priv;
768
 	struct ipoib_device *ipoib = netdev->priv;
760
 	struct ib_device *ibdev = ipoib->ibdev;
769
 	struct ib_device *ibdev = ipoib->ibdev;
761
 
770
 
762
-	ib_poll_cq ( ibdev, ipoib->meta.cq, ipoib_meta_complete_send,
763
-		     ipoib_meta_complete_recv );
764
-	ib_poll_cq ( ibdev, ipoib->data.cq, ipoib_data_complete_send,
765
-		     ipoib_data_complete_recv );
771
+	ib_poll_cq ( ibdev, ipoib->meta.cq );
772
+	ib_poll_cq ( ibdev, ipoib->data.cq );
766
 	ipoib_refill_recv ( ipoib, &ipoib->meta );
773
 	ipoib_refill_recv ( ipoib, &ipoib->meta );
767
 	ipoib_refill_recv ( ipoib, &ipoib->data );
774
 	ipoib_refill_recv ( ipoib, &ipoib->data );
768
 }
775
 }
847
 	if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->meta,
854
 	if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->meta,
848
 					IPOIB_META_NUM_CQES,
855
 					IPOIB_META_NUM_CQES,
849
 					IPOIB_META_NUM_SEND_WQES,
856
 					IPOIB_META_NUM_SEND_WQES,
857
+					ipoib_meta_complete_send,
850
 					IPOIB_META_NUM_RECV_WQES,
858
 					IPOIB_META_NUM_RECV_WQES,
859
+					ipoib_meta_complete_recv,
851
 					IB_GLOBAL_QKEY ) ) != 0 ) {
860
 					IB_GLOBAL_QKEY ) ) != 0 ) {
852
 		DBGC ( ipoib, "IPoIB %p could not allocate metadata QP: %s\n",
861
 		DBGC ( ipoib, "IPoIB %p could not allocate metadata QP: %s\n",
853
 		       ipoib, strerror ( rc ) );
862
 		       ipoib, strerror ( rc ) );
858
 	if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->data,
867
 	if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->data,
859
 					IPOIB_DATA_NUM_CQES,
868
 					IPOIB_DATA_NUM_CQES,
860
 					IPOIB_DATA_NUM_SEND_WQES,
869
 					IPOIB_DATA_NUM_SEND_WQES,
870
+					ipoib_data_complete_send,
861
 					IPOIB_DATA_NUM_RECV_WQES,
871
 					IPOIB_DATA_NUM_RECV_WQES,
872
+					ipoib_data_complete_recv,
862
 					IB_GLOBAL_QKEY ) ) != 0 ) {
873
 					IB_GLOBAL_QKEY ) ) != 0 ) {
863
 		DBGC ( ipoib, "IPoIB %p could not allocate data QP: %s\n",
874
 		DBGC ( ipoib, "IPoIB %p could not allocate data QP: %s\n",
864
 		       ipoib, strerror ( rc ) );
875
 		       ipoib, strerror ( rc ) );

+ 70
- 33
src/include/gpxe/infiniband.h View File

101
 	IB_MODIFY_QKEY = 0x0001,
101
 	IB_MODIFY_QKEY = 0x0001,
102
 };
102
 };
103
 
103
 
104
-/** An Infiniband Completion Queue */
105
-struct ib_completion_queue {
106
-	/** Completion queue number */
107
-	unsigned long cqn;
108
-	/** Number of completion queue entries */
109
-	unsigned int num_cqes;
110
-	/** Next completion queue entry index
111
-	 *
112
-	 * This is the index of the next entry to be filled (i.e. the
113
-	 * first empty entry).  This value is not bounded by num_wqes;
114
-	 * users must logical-AND with (num_wqes-1) to generate an
115
-	 * array index.
116
-	 */
117
-	unsigned long next_idx;
118
-	/** List of work queues completing to this queue */
119
-	struct list_head work_queues;
120
-	/** Driver private data */
121
-	void *drv_priv;
122
-};
123
-
124
 /** An Infiniband completion */
104
 /** An Infiniband completion */
125
 struct ib_completion {
105
 struct ib_completion {
126
 	/** Syndrome
106
 	/** Syndrome
132
 	size_t len;
112
 	size_t len;
133
 };
113
 };
134
 
114
 
115
+/** Infiniband completion syndromes */
116
+enum ib_syndrome {
117
+	IB_SYN_NONE = 0,
118
+	IB_SYN_LOCAL_LENGTH = 1,
119
+	IB_SYN_LOCAL_QP = 2,
120
+	IB_SYN_LOCAL_PROT = 4,
121
+};
122
+
135
 /** An Infiniband completion handler
123
 /** An Infiniband completion handler
136
  *
124
  *
137
  * @v ibdev		Infiniband device
125
  * @v ibdev		Infiniband device
144
 				    struct ib_completion *completion,
132
 				    struct ib_completion *completion,
145
 				    struct io_buffer *iobuf );
133
 				    struct io_buffer *iobuf );
146
 
134
 
135
+/** An Infiniband Completion Queue */
136
+struct ib_completion_queue {
137
+	/** Completion queue number */
138
+	unsigned long cqn;
139
+	/** Number of completion queue entries */
140
+	unsigned int num_cqes;
141
+	/** Next completion queue entry index
142
+	 *
143
+	 * This is the index of the next entry to be filled (i.e. the
144
+	 * first empty entry).  This value is not bounded by num_wqes;
145
+	 * users must logical-AND with (num_wqes-1) to generate an
146
+	 * array index.
147
+	 */
148
+	unsigned long next_idx;
149
+	/** List of work queues completing to this queue */
150
+	struct list_head work_queues;
151
+	/** Send completion handler */
152
+	ib_completer_t complete_send;
153
+	/** Receive completion handler */
154
+	ib_completer_t complete_recv;
155
+	/** Driver private data */
156
+	void *drv_priv;
157
+};
158
+
147
 /** An Infiniband Address Vector */
159
 /** An Infiniband Address Vector */
148
 struct ib_address_vector {
160
 struct ib_address_vector {
149
 	/** Destination Queue Pair */
161
 	/** Destination Queue Pair */
246
 	 *
258
 	 *
247
 	 * @v ibdev		Infiniband device
259
 	 * @v ibdev		Infiniband device
248
 	 * @v cq		Completion queue
260
 	 * @v cq		Completion queue
249
-	 * @v complete_send	Send completion handler
250
-	 * @v complete_recv	Receive completion handler
251
 	 *
261
 	 *
252
-	 * The completion handler takes ownership of the I/O buffer.
262
+	 * The relevant completion handler (specified at completion
263
+	 * queue creation time) takes ownership of the I/O buffer.
253
 	 */
264
 	 */
254
 	void ( * poll_cq ) ( struct ib_device *ibdev,
265
 	void ( * poll_cq ) ( struct ib_device *ibdev,
255
-			     struct ib_completion_queue *cq,
256
-			     ib_completer_t complete_send,
257
-			     ib_completer_t complete_recv );
266
+			     struct ib_completion_queue *cq );
258
 	/**
267
 	/**
259
 	 * Poll event queue
268
 	 * Poll event queue
260
 	 *
269
 	 *
331
 	void *owner_priv;
340
 	void *owner_priv;
332
 };
341
 };
333
 
342
 
334
-extern struct ib_completion_queue * ib_create_cq ( struct ib_device *ibdev,
335
-						   unsigned int num_cqes );
343
+extern struct ib_completion_queue *
344
+ib_create_cq ( struct ib_device *ibdev, unsigned int num_cqes,
345
+	       ib_completer_t complete_send, ib_completer_t complete_recv );
336
 extern void ib_destroy_cq ( struct ib_device *ibdev,
346
 extern void ib_destroy_cq ( struct ib_device *ibdev,
337
 			    struct ib_completion_queue *cq );
347
 			    struct ib_completion_queue *cq );
338
 extern struct ib_queue_pair *
348
 extern struct ib_queue_pair *
379
 	return ibdev->op->post_recv ( ibdev, qp, iobuf );
389
 	return ibdev->op->post_recv ( ibdev, qp, iobuf );
380
 }
390
 }
381
 
391
 
392
+/**
393
+ * Complete send work queue entry
394
+ *
395
+ * @v ibdev		Infiniband device
396
+ * @v qp		Queue pair
397
+ * @v completion	Completion
398
+ * @v iobuf		I/O buffer
399
+ */
400
+static inline __attribute__ (( always_inline )) void
401
+ib_complete_send ( struct ib_device *ibdev, struct ib_queue_pair *qp,
402
+		   struct ib_completion *completion,
403
+		   struct io_buffer *iobuf ) {
404
+	return qp->send.cq->complete_send ( ibdev, qp, completion, iobuf );
405
+}
406
+
407
+/**
408
+ * Complete receive work queue entry
409
+ *
410
+ * @v ibdev		Infiniband device
411
+ * @v qp		Queue pair
412
+ * @v completion	Completion
413
+ * @v iobuf		I/O buffer
414
+ */
415
+static inline __attribute__ (( always_inline )) void
416
+ib_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
417
+		   struct ib_completion *completion,
418
+		   struct io_buffer *iobuf ) {
419
+	return qp->recv.cq->complete_recv ( ibdev, qp, completion, iobuf );
420
+}
421
+
382
 /**
422
 /**
383
  * Poll completion queue
423
  * Poll completion queue
384
  *
424
  *
385
  * @v ibdev		Infiniband device
425
  * @v ibdev		Infiniband device
386
  * @v cq		Completion queue
426
  * @v cq		Completion queue
387
- * @v complete_send	Send completion handler
388
- * @v complete_recv	Receive completion handler
389
  */
427
  */
390
 static inline __attribute__ (( always_inline )) void
428
 static inline __attribute__ (( always_inline )) void
391
-ib_poll_cq ( struct ib_device *ibdev, struct ib_completion_queue *cq,
392
-	     ib_completer_t complete_send, ib_completer_t complete_recv ) {
393
-	ibdev->op->poll_cq ( ibdev, cq, complete_send, complete_recv );
429
+ib_poll_cq ( struct ib_device *ibdev, struct ib_completion_queue *cq ) {
430
+	ibdev->op->poll_cq ( ibdev, cq );
394
 }
431
 }
395
 
432
 
396
 /**
433
 /**

+ 29
- 2
src/net/infiniband.c View File

46
  *
46
  *
47
  * @v ibdev		Infiniband device
47
  * @v ibdev		Infiniband device
48
  * @v num_cqes		Number of completion queue entries
48
  * @v num_cqes		Number of completion queue entries
49
+ * @v complete_send	Send completion handler
50
+ * @v complete_recv	Receive completion handler
49
  * @ret cq		New completion queue
51
  * @ret cq		New completion queue
50
  */
52
  */
51
-struct ib_completion_queue * ib_create_cq ( struct ib_device *ibdev,
52
-					    unsigned int num_cqes ) {
53
+struct ib_completion_queue *
54
+ib_create_cq ( struct ib_device *ibdev, unsigned int num_cqes,
55
+	       ib_completer_t complete_send, ib_completer_t complete_recv ) {
53
 	struct ib_completion_queue *cq;
56
 	struct ib_completion_queue *cq;
54
 	int rc;
57
 	int rc;
55
 
58
 
61
 		return NULL;
64
 		return NULL;
62
 	cq->num_cqes = num_cqes;
65
 	cq->num_cqes = num_cqes;
63
 	INIT_LIST_HEAD ( &cq->work_queues );
66
 	INIT_LIST_HEAD ( &cq->work_queues );
67
+	cq->complete_send = complete_send;
68
+	cq->complete_recv = complete_recv;
64
 
69
 
65
 	/* Perform device-specific initialisation and get CQN */
70
 	/* Perform device-specific initialisation and get CQN */
66
 	if ( ( rc = ibdev->op->create_cq ( ibdev, cq ) ) != 0 ) {
71
 	if ( ( rc = ibdev->op->create_cq ( ibdev, cq ) ) != 0 ) {
190
  * @v qp		Queue pair
195
  * @v qp		Queue pair
191
  */
196
  */
192
 void ib_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
197
 void ib_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) {
198
+	struct ib_completion completion = {
199
+		.syndrome = IB_SYN_LOCAL_QP,
200
+	};
201
+	struct io_buffer *iobuf;
202
+	unsigned int i;
203
+
193
 	DBGC ( ibdev, "IBDEV %p destroying QPN %#lx\n",
204
 	DBGC ( ibdev, "IBDEV %p destroying QPN %#lx\n",
194
 	       ibdev, qp->qpn );
205
 	       ibdev, qp->qpn );
206
+
207
+	/* Perform device-specific destruction */
195
 	ibdev->op->destroy_qp ( ibdev, qp );
208
 	ibdev->op->destroy_qp ( ibdev, qp );
209
+
210
+	/* Complete any remaining I/O buffers with errors */
211
+	for ( i = 0 ; i < qp->send.num_wqes ; i++ ) {
212
+		if ( ( iobuf = qp->send.iobufs[i] ) != NULL )
213
+			ib_complete_send ( ibdev, qp, &completion, iobuf );
214
+	}
215
+	for ( i = 0 ; i < qp->recv.num_wqes ; i++ ) {
216
+		if ( ( iobuf = qp->recv.iobufs[i] ) != NULL )
217
+			ib_complete_recv ( ibdev, qp, &completion, iobuf );
218
+	}
219
+
220
+	/* Remove work queues from completion queue */
196
 	list_del ( &qp->send.list );
221
 	list_del ( &qp->send.list );
197
 	list_del ( &qp->recv.list );
222
 	list_del ( &qp->recv.list );
223
+
224
+	/* Free QP */
198
 	free ( qp );
225
 	free ( qp );
199
 }
226
 }
200
 
227
 

Loading…
Cancel
Save