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 15 years ago
parent
commit
d9751edafa

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

@@ -1106,15 +1106,11 @@ static int arbel_post_recv ( struct ib_device *ibdev,
1106 1106
  * @v ibdev		Infiniband device
1107 1107
  * @v cq		Completion queue
1108 1108
  * @v cqe		Hardware completion queue entry
1109
- * @v complete_send	Send completion handler
1110
- * @v complete_recv	Receive completion handler
1111 1109
  * @ret rc		Return status code
1112 1110
  */
1113 1111
 static int arbel_complete ( struct ib_device *ibdev,
1114 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 1114
 	struct arbel *arbel = ib_get_drvdata ( ibdev );
1119 1115
 	struct ib_completion completion;
1120 1116
 	struct ib_work_queue *wq;
@@ -1124,7 +1120,6 @@ static int arbel_complete ( struct ib_device *ibdev,
1124 1120
 	struct arbel_recv_work_queue *arbel_recv_wq;
1125 1121
 	struct arbelprm_recv_wqe *recv_wqe;
1126 1122
 	struct io_buffer *iobuf;
1127
-	ib_completer_t complete;
1128 1123
 	unsigned int opcode;
1129 1124
 	unsigned long qpn;
1130 1125
 	int is_send;
@@ -1201,8 +1196,11 @@ static int arbel_complete ( struct ib_device *ibdev,
1201 1196
 	}
1202 1197
 
1203 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 1205
 	return rc;
1208 1206
 }			     
@@ -1212,13 +1210,9 @@ static int arbel_complete ( struct ib_device *ibdev,
1212 1210
  *
1213 1211
  * @v ibdev		Infiniband device
1214 1212
  * @v cq		Completion queue
1215
- * @v complete_send	Send completion handler
1216
- * @v complete_recv	Receive completion handler
1217 1213
  */
1218 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 1216
 	struct arbel *arbel = ib_get_drvdata ( ibdev );
1223 1217
 	struct arbel_completion_queue *arbel_cq = ib_cq_get_drvdata ( cq );
1224 1218
 	struct arbelprm_cq_ci_db_record *ci_db_rec;
@@ -1236,8 +1230,7 @@ static void arbel_poll_cq ( struct ib_device *ibdev,
1236 1230
 		}
1237 1231
 
1238 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 1234
 			DBGC ( arbel, "Arbel %p failed to complete: %s\n",
1242 1235
 			       arbel, strerror ( rc ) );
1243 1236
 			DBGC_HD ( arbel, cqe, sizeof ( *cqe ) );

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

@@ -1101,22 +1101,17 @@ static int hermon_post_recv ( struct ib_device *ibdev,
1101 1101
  * @v ibdev		Infiniband device
1102 1102
  * @v cq		Completion queue
1103 1103
  * @v cqe		Hardware completion queue entry
1104
- * @v complete_send	Send completion handler
1105
- * @v complete_recv	Receive completion handler
1106 1104
  * @ret rc		Return status code
1107 1105
  */
1108 1106
 static int hermon_complete ( struct ib_device *ibdev,
1109 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 1109
 	struct hermon *hermon = ib_get_drvdata ( ibdev );
1114 1110
 	struct ib_completion completion;
1115 1111
 	struct ib_work_queue *wq;
1116 1112
 	struct ib_queue_pair *qp;
1117 1113
 	struct hermon_queue_pair *hermon_qp;
1118 1114
 	struct io_buffer *iobuf;
1119
-	ib_completer_t complete;
1120 1115
 	unsigned int opcode;
1121 1116
 	unsigned long qpn;
1122 1117
 	int is_send;
@@ -1172,8 +1167,11 @@ static int hermon_complete ( struct ib_device *ibdev,
1172 1167
 	}
1173 1168
 
1174 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 1176
 	return rc;
1179 1177
 }
@@ -1183,13 +1181,9 @@ static int hermon_complete ( struct ib_device *ibdev,
1183 1181
  *
1184 1182
  * @v ibdev		Infiniband device
1185 1183
  * @v cq		Completion queue
1186
- * @v complete_send	Send completion handler
1187
- * @v complete_recv	Receive completion handler
1188 1184
  */
1189 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 1187
 	struct hermon *hermon = ib_get_drvdata ( ibdev );
1194 1188
 	struct hermon_completion_queue *hermon_cq = ib_cq_get_drvdata ( cq );
1195 1189
 	union hermonprm_completion_entry *cqe;
@@ -1209,8 +1203,7 @@ static void hermon_poll_cq ( struct ib_device *ibdev,
1209 1203
 		DBGCP_HD ( hermon, cqe, sizeof ( *cqe ) );
1210 1204
 
1211 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 1207
 			DBGC ( hermon, "Hermon %p failed to complete: %s\n",
1215 1208
 			       hermon, strerror ( rc ) );
1216 1209
 			DBGC_HD ( hermon, cqe, sizeof ( *cqe ) );

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

@@ -278,13 +278,21 @@ static void ipoib_destroy_qset ( struct ipoib_device *ipoib,
278 278
  *
279 279
  * @v ipoib		IPoIB device
280 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 287
  * @ret rc		Return status code
282 288
  */
283 289
 static int ipoib_create_qset ( struct ipoib_device *ipoib,
284 290
 			       struct ipoib_queue_set *qset,
285 291
 			       unsigned int num_cqes,
286 292
 			       unsigned int num_send_wqes,
293
+			       ib_completer_t complete_send,
287 294
 			       unsigned int num_recv_wqes,
295
+			       ib_completer_t complete_recv,
288 296
 			       unsigned long qkey ) {
289 297
 	struct ib_device *ibdev = ipoib->ibdev;
290 298
 	int rc;
@@ -297,7 +305,8 @@ static int ipoib_create_qset ( struct ipoib_device *ipoib,
297 305
 	qset->recv_max_fill = num_recv_wqes;
298 306
 
299 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 310
 	if ( ! qset->cq ) {
302 311
 		DBGC ( ipoib, "IPoIB %p could not allocate completion queue\n",
303 312
 		       ipoib );
@@ -759,10 +768,8 @@ static void ipoib_poll ( struct net_device *netdev ) {
759 768
 	struct ipoib_device *ipoib = netdev->priv;
760 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 773
 	ipoib_refill_recv ( ipoib, &ipoib->meta );
767 774
 	ipoib_refill_recv ( ipoib, &ipoib->data );
768 775
 }
@@ -847,7 +854,9 @@ static int ipoib_open ( struct net_device *netdev ) {
847 854
 	if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->meta,
848 855
 					IPOIB_META_NUM_CQES,
849 856
 					IPOIB_META_NUM_SEND_WQES,
857
+					ipoib_meta_complete_send,
850 858
 					IPOIB_META_NUM_RECV_WQES,
859
+					ipoib_meta_complete_recv,
851 860
 					IB_GLOBAL_QKEY ) ) != 0 ) {
852 861
 		DBGC ( ipoib, "IPoIB %p could not allocate metadata QP: %s\n",
853 862
 		       ipoib, strerror ( rc ) );
@@ -858,7 +867,9 @@ static int ipoib_open ( struct net_device *netdev ) {
858 867
 	if ( ( rc = ipoib_create_qset ( ipoib, &ipoib->data,
859 868
 					IPOIB_DATA_NUM_CQES,
860 869
 					IPOIB_DATA_NUM_SEND_WQES,
870
+					ipoib_data_complete_send,
861 871
 					IPOIB_DATA_NUM_RECV_WQES,
872
+					ipoib_data_complete_recv,
862 873
 					IB_GLOBAL_QKEY ) ) != 0 ) {
863 874
 		DBGC ( ipoib, "IPoIB %p could not allocate data QP: %s\n",
864 875
 		       ipoib, strerror ( rc ) );

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

@@ -101,26 +101,6 @@ enum ib_queue_pair_mods {
101 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 104
 /** An Infiniband completion */
125 105
 struct ib_completion {
126 106
 	/** Syndrome
@@ -132,6 +112,14 @@ struct ib_completion {
132 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 123
 /** An Infiniband completion handler
136 124
  *
137 125
  * @v ibdev		Infiniband device
@@ -144,6 +132,30 @@ typedef void ( * ib_completer_t ) ( struct ib_device *ibdev,
144 132
 				    struct ib_completion *completion,
145 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 159
 /** An Infiniband Address Vector */
148 160
 struct ib_address_vector {
149 161
 	/** Destination Queue Pair */
@@ -246,15 +258,12 @@ struct ib_device_operations {
246 258
 	 *
247 259
 	 * @v ibdev		Infiniband device
248 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 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 268
 	 * Poll event queue
260 269
 	 *
@@ -331,8 +340,9 @@ struct ib_device {
331 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 346
 extern void ib_destroy_cq ( struct ib_device *ibdev,
337 347
 			    struct ib_completion_queue *cq );
338 348
 extern struct ib_queue_pair *
@@ -379,18 +389,45 @@ ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp,
379 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 423
  * Poll completion queue
384 424
  *
385 425
  * @v ibdev		Infiniband device
386 426
  * @v cq		Completion queue
387
- * @v complete_send	Send completion handler
388
- * @v complete_recv	Receive completion handler
389 427
  */
390 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,10 +46,13 @@ struct list_head ib_devices = LIST_HEAD_INIT ( ib_devices );
46 46
  *
47 47
  * @v ibdev		Infiniband device
48 48
  * @v num_cqes		Number of completion queue entries
49
+ * @v complete_send	Send completion handler
50
+ * @v complete_recv	Receive completion handler
49 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 56
 	struct ib_completion_queue *cq;
54 57
 	int rc;
55 58
 
@@ -61,6 +64,8 @@ struct ib_completion_queue * ib_create_cq ( struct ib_device *ibdev,
61 64
 		return NULL;
62 65
 	cq->num_cqes = num_cqes;
63 66
 	INIT_LIST_HEAD ( &cq->work_queues );
67
+	cq->complete_send = complete_send;
68
+	cq->complete_recv = complete_recv;
64 69
 
65 70
 	/* Perform device-specific initialisation and get CQN */
66 71
 	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,
190 195
  * @v qp		Queue pair
191 196
  */
192 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 204
 	DBGC ( ibdev, "IBDEV %p destroying QPN %#lx\n",
194 205
 	       ibdev, qp->qpn );
206
+
207
+	/* Perform device-specific destruction */
195 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 221
 	list_del ( &qp->send.list );
197 222
 	list_del ( &qp->recv.list );
223
+
224
+	/* Free QP */
198 225
 	free ( qp );
199 226
 }
200 227
 

Loading…
Cancel
Save