Browse Source

Direct polling of TX completion queue now works.

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
8deef093d9

+ 79
- 0
src/drivers/net/mlx_ipoib/arbel.h View File

1
 #ifndef _ARBEL_H
1
 #ifndef _ARBEL_H
2
 #define _ARBEL_H
2
 #define _ARBEL_H
3
 
3
 
4
+/** @file
5
+ *
6
+ * Mellanox Arbel Infiniband HCA driver
7
+ *
8
+ */
9
+
10
+/*
11
+ * Hardware constants
12
+ *
13
+ */
14
+
15
+#define ARBEL_OPCODE_SEND		0x0a
16
+#define ARBEL_OPCODE_RECV_ERROR		0xfe
17
+#define ARBEL_OPCODE_SEND_ERROR		0xff
18
+
19
+/*
20
+ * Wrapper structures for hardware datatypes
21
+ *
22
+ */
23
+
4
 struct MLX_DECLARE_STRUCT ( arbelprm_completion_queue_entry );
24
 struct MLX_DECLARE_STRUCT ( arbelprm_completion_queue_entry );
5
 struct MLX_DECLARE_STRUCT ( arbelprm_completion_with_error );
25
 struct MLX_DECLARE_STRUCT ( arbelprm_completion_with_error );
6
 struct MLX_DECLARE_STRUCT ( arbelprm_cq_ci_db_record );
26
 struct MLX_DECLARE_STRUCT ( arbelprm_cq_ci_db_record );
12
 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_next );
32
 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_next );
13
 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_ud );
33
 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_ud );
14
 
34
 
35
+/*
36
+ * Composite hardware datatypes
37
+ *
38
+ */
39
+
15
 #define ARBELPRM_MAX_GATHER 1
40
 #define ARBELPRM_MAX_GATHER 1
16
 
41
 
17
 struct arbelprm_ud_send_wqe {
42
 struct arbelprm_ud_send_wqe {
36
 	uint32_t dword[2];
61
 	uint32_t dword[2];
37
 } __attribute__ (( packed ));
62
 } __attribute__ (( packed ));
38
 
63
 
64
+/*
65
+ * gPXE-specific definitions
66
+ *
67
+ */
68
+
69
+/** Alignment of Arbel send work queue entries */
70
+#define ARBEL_SEND_WQE_ALIGN 128
71
+
72
+/** An Arbel send work queue entry */
73
+union arbel_send_wqe {
74
+	struct arbelprm_ud_send_wqe ud;
75
+	uint8_t force_align[ARBEL_SEND_WQE_ALIGN];
76
+} __attribute__ (( packed ));
77
+
78
+/** An Arbel send work queue */
79
+struct arbel_send_work_queue {
80
+	/** Doorbell record number */
81
+	unsigned int doorbell_idx;
82
+	/** Work queue entries */
83
+	union arbel_send_wqe *wqe;
84
+};
85
+
86
+/** Alignment of Arbel receive work queue entries */
87
+#define ARBEL_RECV_WQE_ALIGN 64
88
+
89
+/** An Arbel receive work queue entry */
90
+union arbel_recv_wqe {
91
+	uint8_t force_align[ARBEL_RECV_WQE_ALIGN];
92
+} __attribute__ (( packed ));
93
+
94
+/** An Arbel receive work queue */
95
+struct arbel_recv_work_queue {
96
+	/** Doorbell record number */
97
+	unsigned int doorbell_idx;
98
+	/** Work queue entries */
99
+	union arbel_recv_wqe *wqe;
100
+};
101
+
102
+/** An Arbel completion queue */
103
+struct arbel_completion_queue {
104
+	/** Doorbell record number */
105
+	unsigned int doorbell_idx;
106
+	/** Completion queue entries */
107
+	union arbelprm_completion_entry *cqe;
108
+};
109
+
110
+/** An Arbel device */
111
+struct arbel {
112
+	/** User Access Region */
113
+	void *uar;
114
+	/** Doorbell records */
115
+	union arbelprm_doorbell_record *db_rec;
116
+};
117
+
39
 #endif /* _ARBEL_H */
118
 #endif /* _ARBEL_H */

+ 190
- 61
src/drivers/net/mlx_ipoib/mt25218.c View File

25
 
25
 
26
 #include "arbel.h"
26
 #include "arbel.h"
27
 
27
 
28
-struct arbel_send_work_queue {
29
-	/** Doorbell record number */
30
-	unsigned int doorbell_idx;
31
-	/** Work queue entries */
32
-	//	struct ud_send_wqe_st *wqe;
33
-	union ud_send_wqe_u *wqe_u;
34
-};
35
-
36
-struct arbel_completion_queue {
37
-	/** Doorbell record number */
38
-	unsigned int doorbell_idx;
39
-	/** Completion queue entries */
40
-	union arbelprm_completion_entry *cqe;
41
-};
42
-
43
-struct arbel {
44
-	/** User Access Region */
45
-	void *uar;
46
-	/** Doorbell records */
47
-	union arbelprm_doorbell_record *db_rec;
48
-};
49
-
50
 
28
 
51
 
29
 
52
 struct mlx_nic {
30
 struct mlx_nic {
119
 	return 0;
97
 	return 0;
120
 }
98
 }
121
 
99
 
122
-static int arbel_post_send ( struct ib_device *ibdev, struct io_buffer *iobuf,
100
+static int arbel_post_send ( struct ib_device *ibdev,
101
+			     struct ib_queue_pair *qp,
123
 			     struct ib_address_vector *av,
102
 			     struct ib_address_vector *av,
124
-			     struct ib_queue_pair *qp );
103
+			     struct io_buffer *iobuf );
125
 
104
 
126
 static struct io_buffer *tx_ring[NUM_IPOIB_SND_WQES];
105
 static struct io_buffer *tx_ring[NUM_IPOIB_SND_WQES];
127
 static int next_tx_idx = 0;
106
 static int next_tx_idx = 0;
137
 	};
116
 	};
138
 	struct arbel_send_work_queue arbel_send_queue = {
117
 	struct arbel_send_work_queue arbel_send_queue = {
139
 		.doorbell_idx = IPOIB_SND_QP_DB_IDX,
118
 		.doorbell_idx = IPOIB_SND_QP_DB_IDX,
140
-		.wqe_u = ( (struct udqp_st *) mlx->ipoib_qph )->snd_wq,
119
+		.wqe = ( (struct udqp_st *) mlx->ipoib_qph )->snd_wq,
141
 	};
120
 	};
142
 	struct ib_device ibdev = {
121
 	struct ib_device ibdev = {
143
-		.priv = &arbel,
122
+		.dev_priv = &arbel,
144
 	};
123
 	};
145
 	struct ib_queue_pair qp = {
124
 	struct ib_queue_pair qp = {
146
 		.qpn = ib_get_qpn ( mlx->ipoib_qph ),
125
 		.qpn = ib_get_qpn ( mlx->ipoib_qph ),
148
 			.num_wqes = NUM_IPOIB_SND_WQES,
127
 			.num_wqes = NUM_IPOIB_SND_WQES,
149
 			.next_idx = next_tx_idx,
128
 			.next_idx = next_tx_idx,
150
 			.iobufs = tx_ring,
129
 			.iobufs = tx_ring,
151
-			.priv = &arbel_send_queue,
130
+			.dev_priv = &arbel_send_queue,
152
 		},
131
 		},
153
 	};
132
 	};
154
 	struct ud_av_st *bcast_av = mlx->bcast_av;
133
 	struct ud_av_st *bcast_av = mlx->bcast_av;
164
 	};
143
 	};
165
 	memcpy ( &av.gid, ( ( void * ) bav ) + 16, 16 );
144
 	memcpy ( &av.gid, ( ( void * ) bav ) + 16, 16 );
166
 
145
 
167
-	rc = arbel_post_send ( &ibdev, iobuf, &av, &qp );
146
+	rc = arbel_post_send ( &ibdev, &qp, &av, iobuf );
168
 
147
 
169
 	next_tx_idx = qp.send.next_idx;
148
 	next_tx_idx = qp.send.next_idx;
170
 
149
 
172
 }
151
 }
173
 
152
 
174
 
153
 
154
+static void arbel_poll_cq ( struct ib_device *ibdev,
155
+			    struct ib_completion_queue *cq,
156
+			    ib_completer_t complete_send,
157
+			    ib_completer_t complete_recv );
158
+
159
+static void temp_complete_send ( struct ib_device *ibdev __unused,
160
+				 struct ib_queue_pair *qp,
161
+				 struct ib_completion *completion,
162
+				 struct io_buffer *iobuf ) {
163
+	struct net_device *netdev = qp->priv;
164
+
165
+	DBG ( "Wahey! TX completion\n" );
166
+	netdev_tx_complete_err ( netdev, iobuf,
167
+				 ( completion->syndrome ? -EIO : 0 ) );
168
+}
169
+
170
+static void temp_complete_recv ( struct ib_device *ibdev __unused,
171
+				 struct ib_queue_pair *qp __unused,
172
+				 struct ib_completion *completion __unused,
173
+				 struct io_buffer *iobuf __unused ) {
174
+	DBG ( "AARGH! recv completion\n" );
175
+}
176
+
177
+static int next_cq_idx = 0;
178
+
179
+static void mlx_poll_cq_direct ( struct net_device *netdev ) {
180
+	struct mlx_nic *mlx = netdev->priv;
181
+
182
+	struct arbel arbel = {
183
+		.uar = memfree_pci_dev.uar,
184
+		.db_rec = dev_ib_data.uar_context_base,
185
+	};
186
+	struct arbel_send_work_queue arbel_send_queue = {
187
+		.doorbell_idx = IPOIB_SND_QP_DB_IDX,
188
+		.wqe = ( ( struct udqp_st * ) mlx->ipoib_qph )->snd_wq,
189
+	};
190
+	struct ib_device ibdev = {
191
+		.dev_priv = &arbel,
192
+	};
193
+	struct ib_queue_pair qp = {
194
+		.qpn = ib_get_qpn ( mlx->ipoib_qph ),
195
+		.send = {
196
+			.num_wqes = NUM_IPOIB_SND_WQES,
197
+			.next_idx = next_tx_idx,
198
+			.iobufs = tx_ring,
199
+			.dev_priv = &arbel_send_queue,
200
+		},
201
+		.priv = netdev,
202
+	};
203
+	struct arbel_completion_queue arbel_cq = {
204
+		.doorbell_idx = IPOIB_SND_CQ_CI_DB_IDX,
205
+		.cqe = ( ( struct cq_st * ) mlx->snd_cqh )->cq_buf,
206
+	};
207
+	struct ib_completion_queue cq = {
208
+		.cqn = 1234,
209
+		.num_cqes = NUM_IPOIB_SND_CQES,
210
+		.next_idx = next_cq_idx, 
211
+		.dev_priv = &arbel_cq,
212
+	};
213
+
214
+	INIT_LIST_HEAD ( &cq.queue_pairs );
215
+	INIT_LIST_HEAD ( &qp.list );
216
+	list_add ( &qp.list, &cq.queue_pairs );
217
+
218
+	arbel_poll_cq ( &ibdev, &cq, temp_complete_send, temp_complete_recv );
219
+
220
+	next_cq_idx = cq.next_idx;
221
+}
222
+
175
 /**
223
 /**
176
  * Handle TX completion
224
  * Handle TX completion
177
  *
225
  *
276
 	}
324
 	}
277
 
325
 
278
 	/* Poll completion queues */
326
 	/* Poll completion queues */
327
+#if 0
279
 	mlx_poll_cq ( netdev, mlx->snd_cqh, mlx_tx_complete );
328
 	mlx_poll_cq ( netdev, mlx->snd_cqh, mlx_tx_complete );
329
+#else
330
+	mlx_poll_cq_direct ( netdev );
331
+#endif
280
 	mlx_poll_cq ( netdev, mlx->rcv_cqh, mlx_rx_complete );
332
 	mlx_poll_cq ( netdev, mlx->rcv_cqh, mlx_rx_complete );
281
 }
333
 }
282
 
334
 
336
  * Post send work queue entry
388
  * Post send work queue entry
337
  *
389
  *
338
  * @v ibdev		Infiniband device
390
  * @v ibdev		Infiniband device
339
- * @v iobuf		I/O buffer
340
- * @v av		Address vector
341
  * @v qp		Queue pair
391
  * @v qp		Queue pair
392
+ * @v av		Address vector
393
+ * @v iobuf		I/O buffer
342
  * @ret rc		Return status code
394
  * @ret rc		Return status code
343
  */
395
  */
344
-static int arbel_post_send ( struct ib_device *ibdev, struct io_buffer *iobuf,
396
+static int arbel_post_send ( struct ib_device *ibdev,
397
+			     struct ib_queue_pair *qp,
345
 			     struct ib_address_vector *av,
398
 			     struct ib_address_vector *av,
346
-			     struct ib_queue_pair *qp ) {
347
-	struct arbel *arbel = ibdev->priv;
399
+			     struct io_buffer *iobuf ) {
400
+	struct arbel *arbel = ibdev->dev_priv;
348
 	struct ib_work_queue *wq = &qp->send;
401
 	struct ib_work_queue *wq = &qp->send;
349
-	struct arbel_send_work_queue *arbel_wq = wq->priv;
402
+	struct arbel_send_work_queue *arbel_send_wq = wq->dev_priv;
350
 	struct arbelprm_ud_send_wqe *prev_wqe;
403
 	struct arbelprm_ud_send_wqe *prev_wqe;
351
 	struct arbelprm_ud_send_wqe *wqe;
404
 	struct arbelprm_ud_send_wqe *wqe;
352
 	union arbelprm_doorbell_record *db_rec;
405
 	union arbelprm_doorbell_record *db_rec;
358
 	/* Allocate work queue entry */
411
 	/* Allocate work queue entry */
359
 	wqe_idx_mask = ( wq->num_wqes - 1 );
412
 	wqe_idx_mask = ( wq->num_wqes - 1 );
360
 	if ( wq->iobufs[wq->next_idx & wqe_idx_mask] ) {
413
 	if ( wq->iobufs[wq->next_idx & wqe_idx_mask] ) {
361
-		DBGC ( arbel, "ARBEL %p send queue full", arbel );
414
+		DBGC ( arbel, "Arbel %p send queue full", arbel );
362
 		return -ENOBUFS;
415
 		return -ENOBUFS;
363
 	}
416
 	}
364
 	wq->iobufs[wq->next_idx & wqe_idx_mask] = iobuf;
417
 	wq->iobufs[wq->next_idx & wqe_idx_mask] = iobuf;
365
-	prev_wqe = &arbel_wq->wqe_u[(wq->next_idx - 1) & wqe_idx_mask].wqe_cont.wqe;
366
-	wqe = &arbel_wq->wqe_u[wq->next_idx & wqe_idx_mask].wqe_cont.wqe;
418
+	prev_wqe = &arbel_send_wq->wqe[(wq->next_idx - 1) & wqe_idx_mask].ud;
419
+	wqe = &arbel_send_wq->wqe[wq->next_idx & wqe_idx_mask].ud;
367
 
420
 
368
 	/* Construct work queue entry */
421
 	/* Construct work queue entry */
369
 	MLX_FILL_1 ( &wqe->next, 1, always1, 1 );
422
 	MLX_FILL_1 ( &wqe->next, 1, always1, 1 );
395
 	/* Update previous work queue entry's "next" field */
448
 	/* Update previous work queue entry's "next" field */
396
 	nds = ( ( offsetof ( typeof ( *wqe ), data ) +
449
 	nds = ( ( offsetof ( typeof ( *wqe ), data ) +
397
 		  sizeof ( wqe->data[0] ) ) >> 4 );
450
 		  sizeof ( wqe->data[0] ) ) >> 4 );
398
-	MLX_SET ( &prev_wqe->next, nopcode, XDEV_NOPCODE_SEND );
451
+	MLX_SET ( &prev_wqe->next, nopcode, ARBEL_OPCODE_SEND );
399
 	MLX_FILL_3 ( &prev_wqe->next, 1,
452
 	MLX_FILL_3 ( &prev_wqe->next, 1,
400
 		     nds, nds,
453
 		     nds, nds,
401
 		     f, 1,
454
 		     f, 1,
405
 	DBG_HD ( &prev_wqe->next, sizeof ( prev_wqe->next ) );
458
 	DBG_HD ( &prev_wqe->next, sizeof ( prev_wqe->next ) );
406
 
459
 
407
 	/* Update doorbell record */
460
 	/* Update doorbell record */
408
-	db_rec = &arbel->db_rec[arbel_wq->doorbell_idx];
461
+	db_rec = &arbel->db_rec[arbel_send_wq->doorbell_idx];
409
 	MLX_FILL_1 ( &db_rec->qp, 0,
462
 	MLX_FILL_1 ( &db_rec->qp, 0,
410
 		     counter, ( ( wq->next_idx + 1 ) & 0xffff ) );
463
 		     counter, ( ( wq->next_idx + 1 ) & 0xffff ) );
411
 	barrier();
464
 	barrier();
414
 
467
 
415
 	/* Ring doorbell register */
468
 	/* Ring doorbell register */
416
 	MLX_FILL_4 ( &db_reg.send, 0,
469
 	MLX_FILL_4 ( &db_reg.send, 0,
417
-		     nopcode, XDEV_NOPCODE_SEND,
470
+		     nopcode, ARBEL_OPCODE_SEND,
418
 		     f, 1,
471
 		     f, 1,
419
 		     wqe_counter, ( wq->next_idx & 0xffff ),
472
 		     wqe_counter, ( wq->next_idx & 0xffff ),
420
 		     wqe_cnt, 1 );
473
 		     wqe_cnt, 1 );
429
 	return 0;
482
 	return 0;
430
 }
483
 }
431
 
484
 
432
-static void arbel_parse_completion ( struct arbel *arbel,
433
-				     union arbelprm_completion_entry *cqe,
434
-				     struct ib_completion *completion ) {
435
-	memset ( completion, 0, sizeof ( *completion ) );
436
-	completion->is_send = MLX_GET ( &cqe->normal, s );
437
-	completion->len = MLX_GET ( &cqe->normal, byte_cnt );
438
-}
485
+/**
486
+ * Handle completion
487
+ *
488
+ * @v ibdev		Infiniband device
489
+ * @v cq		Completion queue
490
+ * @v cqe		Hardware completion queue entry
491
+ * @v complete_send	Send completion handler
492
+ * @v complete_recv	Receive completion handler
493
+ * @ret rc		Return status code
494
+ */
495
+static int arbel_complete ( struct ib_device *ibdev,
496
+			    struct ib_completion_queue *cq,
497
+			    union arbelprm_completion_entry *cqe,
498
+			    ib_completer_t complete_send,
499
+			    ib_completer_t complete_recv ) {
500
+	struct arbel *arbel = ibdev->dev_priv;
501
+	struct ib_completion completion;
502
+	struct ib_queue_pair *qp;
503
+	struct ib_work_queue *wq;
504
+	struct io_buffer *iobuf;
505
+	struct arbel_send_work_queue *arbel_send_wq;
506
+	struct arbel_recv_work_queue *arbel_recv_wq;
507
+	ib_completer_t complete;
508
+	unsigned int opcode;
509
+	unsigned long qpn;
510
+	unsigned int is_send;
511
+	unsigned long wqe_adr;
512
+	unsigned int wqe_idx;
513
+	int rc = 0;
514
+
515
+	/* Parse completion */
516
+	memset ( &completion, 0, sizeof ( completion ) );
517
+	completion.len = MLX_GET ( &cqe->normal, byte_cnt );
518
+	qpn = MLX_GET ( &cqe->normal, my_qpn );
519
+	is_send = MLX_GET ( &cqe->normal, s );
520
+	wqe_adr = ( MLX_GET ( &cqe->normal, wqe_adr ) << 6 );
521
+	opcode = MLX_GET ( &cqe->normal, opcode );
522
+	if ( opcode >= ARBEL_OPCODE_RECV_ERROR ) {
523
+		/* "s" field is not valid for error opcodes */
524
+		is_send = ( opcode == ARBEL_OPCODE_SEND_ERROR );
525
+		completion.syndrome = MLX_GET ( &cqe->error, syndrome );
526
+		DBGC ( arbel, "Arbel %p CPN %lx syndrome %x vendor %lx\n",
527
+		       arbel, cq->cqn, completion.syndrome,
528
+		       MLX_GET ( &cqe->error, vendor_code ) );
529
+		rc = -EIO;
530
+		/* Don't return immediately; propagate error to completer */
531
+	}
532
+
533
+	/* Identify queue pair */
534
+	qp = ib_find_qp ( &cq->queue_pairs, qpn );
535
+	if ( ! qp ) {
536
+		DBGC ( arbel, "Arbel %p CQN %lx unknown QPN %lx\n",
537
+		       arbel, cq->cqn, qpn );
538
+		return -EIO;
539
+	}
540
+
541
+	/* Identify work queue entry index */
542
+	if ( is_send ) {
543
+		wq = &qp->send;
544
+		arbel_send_wq = wq->dev_priv;
545
+		wqe_idx = ( ( wqe_adr - virt_to_bus ( arbel_send_wq->wqe ) ) /
546
+			    sizeof ( arbel_send_wq->wqe[0] ) );
547
+	} else {
548
+		wq = &qp->recv;
549
+		arbel_recv_wq = wq->dev_priv;
550
+		wqe_idx = ( ( wqe_adr - virt_to_bus ( arbel_recv_wq->wqe ) ) /
551
+			    sizeof ( arbel_recv_wq->wqe[0] ) );
552
+	}
553
+
554
+	/* Identify I/O buffer */
555
+	iobuf = wq->iobufs[wqe_idx];
556
+	if ( ! iobuf ) {
557
+		DBGC ( arbel, "Arbel %p CQN %lx QPN %lx empty WQE %x\n",
558
+		       arbel, cq->cqn, qpn, wqe_idx );
559
+		return -EIO;
560
+	}
561
+	wq->iobufs[wqe_idx] = NULL;
562
+
563
+	/* Pass off to caller's completion handler */
564
+	complete = ( is_send ? complete_send : complete_recv );
565
+	complete ( ibdev, qp, &completion, iobuf );
566
+
567
+	return rc;
568
+}			     
439
 
569
 
440
 /**
570
 /**
441
  * Poll completion queue
571
  * Poll completion queue
442
  *
572
  *
443
  * @v ibdev		Infiniband device
573
  * @v ibdev		Infiniband device
444
  * @v cq		Completion queue
574
  * @v cq		Completion queue
445
- * @v complete		Completion handler
575
+ * @v complete_send	Send completion handler
576
+ * @v complete_recv	Receive completion handler
446
  */
577
  */
447
 static void arbel_poll_cq ( struct ib_device *ibdev,
578
 static void arbel_poll_cq ( struct ib_device *ibdev,
448
 			    struct ib_completion_queue *cq,
579
 			    struct ib_completion_queue *cq,
449
 			    ib_completer_t complete_send,
580
 			    ib_completer_t complete_send,
450
 			    ib_completer_t complete_recv ) {
581
 			    ib_completer_t complete_recv ) {
451
-	struct arbel *arbel = ibdev->priv;
452
-	struct arbel_completion_queue *arbel_cq = cq->priv;
453
-	unsigned int cqe_idx_mask = ( cq->num_cqes - 1 );
582
+	struct arbel *arbel = ibdev->dev_priv;
583
+	struct arbel_completion_queue *arbel_cq = cq->dev_priv;
454
 	union arbelprm_doorbell_record *db_rec;
584
 	union arbelprm_doorbell_record *db_rec;
455
 	union arbelprm_completion_entry *cqe;
585
 	union arbelprm_completion_entry *cqe;
456
-	struct ib_completion completion;
457
-	struct io_buffer *iobuf;
458
-	int is_send;
586
+	unsigned int cqe_idx_mask;
587
+	int rc;
459
 
588
 
460
 	while ( 1 ) {
589
 	while ( 1 ) {
461
 		/* Look for completion entry */
590
 		/* Look for completion entry */
591
+		cqe_idx_mask = ( cq->num_cqes - 1 );
462
 		cqe = &arbel_cq->cqe[cq->next_idx & cqe_idx_mask];
592
 		cqe = &arbel_cq->cqe[cq->next_idx & cqe_idx_mask];
463
 		if ( MLX_GET ( &cqe->normal, owner ) != 0 ) {
593
 		if ( MLX_GET ( &cqe->normal, owner ) != 0 ) {
464
 			/* Entry still owned by hardware; end of poll */
594
 			/* Entry still owned by hardware; end of poll */
465
 			break;
595
 			break;
466
 		}
596
 		}
467
 
597
 
468
-		/* Parse completion */
469
-
470
-		
471
-		
472
 		/* Handle completion */
598
 		/* Handle completion */
473
-		( is_send ? complete_send : complete_recv ) ( ibdev,
474
-							      &completion,
475
-							      iobuf );
599
+		if ( ( rc = arbel_complete ( ibdev, cq, cqe, complete_send,
600
+					     complete_recv ) ) != 0 ) {
601
+			DBGC ( arbel, "Arbel %p failed to complete: %s\n",
602
+			       arbel, strerror ( rc ) );
603
+			DBGC_HD ( arbel, cqe, sizeof ( *cqe ) );
604
+		}
476
 
605
 
477
 		/* Return ownership to hardware */
606
 		/* Return ownership to hardware */
478
 		MLX_FILL_1 ( &cqe->normal, 7, owner, 1 );
607
 		MLX_FILL_1 ( &cqe->normal, 7, owner, 1 );

+ 30
- 14
src/include/gpxe/infiniband.h View File

79
 	unsigned long next_idx;
79
 	unsigned long next_idx;
80
 	/** I/O buffers assigned to work queue */
80
 	/** I/O buffers assigned to work queue */
81
 	struct io_buffer **iobufs;
81
 	struct io_buffer **iobufs;
82
-	/** Driver private data */
83
-	void *priv;
82
+	/** Device private data */
83
+	void *dev_priv;
84
 };
84
 };
85
 
85
 
86
 /** An Infiniband Queue Pair */
86
 /** An Infiniband Queue Pair */
87
 struct ib_queue_pair {
87
 struct ib_queue_pair {
88
+	/** List of queue pairs sharing a completion queue */
89
+	struct list_head list;
88
 	/** Queue Pair Number */
90
 	/** Queue Pair Number */
89
-	uint32_t qpn;
91
+	unsigned long qpn;
90
 	/** Send queue */
92
 	/** Send queue */
91
 	struct ib_work_queue send;
93
 	struct ib_work_queue send;
92
 	/** Receive queue */
94
 	/** Receive queue */
93
 	struct ib_work_queue recv;
95
 	struct ib_work_queue recv;
94
-	/** Driver private data */
96
+	/** Queue owner private data */
95
 	void *priv;
97
 	void *priv;
98
+	/** Device private data */
99
+	void *dev_priv;
96
 };
100
 };
97
 
101
 
98
 /** An Infiniband Completion Queue */
102
 /** An Infiniband Completion Queue */
99
 struct ib_completion_queue {
103
 struct ib_completion_queue {
104
+	/** Completion queue number */
105
+	unsigned long cqn;
100
 	/** Number of completion queue entries */
106
 	/** Number of completion queue entries */
101
 	unsigned int num_cqes;
107
 	unsigned int num_cqes;
102
 	/** Next completion queue entry index
108
 	/** Next completion queue entry index
107
 	 * array index.
113
 	 * array index.
108
 	 */
114
 	 */
109
 	unsigned long next_idx;
115
 	unsigned long next_idx;
110
-	/** Driver private data */
111
-	void *priv;
116
+	/** List of associated queue pairs */
117
+	struct list_head queue_pairs;
118
+	/** Device private data */
119
+	void *dev_priv;
112
 };
120
 };
113
 
121
 
114
 /** An Infiniband completion */
122
 /** An Infiniband completion */
115
 struct ib_completion {
123
 struct ib_completion {
116
-	/** Completion is for send queue */
117
-	int is_send;
124
+	/** Syndrome
125
+	 *
126
+	 * If non-zero, then the completion is in error.
127
+	 */
128
+	unsigned int syndrome;
118
 	/** Length */
129
 	/** Length */
119
 	size_t len;
130
 	size_t len;
120
 };
131
 };
122
 /** An Infiniband completion handler
133
 /** An Infiniband completion handler
123
  *
134
  *
124
  * @v ibdev		Infiniband device
135
  * @v ibdev		Infiniband device
136
+ * @v qp		Queue pair
125
  * @v completion	Completion
137
  * @v completion	Completion
126
  * @v iobuf		I/O buffer
138
  * @v iobuf		I/O buffer
127
  */
139
  */
128
 typedef void ( * ib_completer_t ) ( struct ib_device *ibdev,
140
 typedef void ( * ib_completer_t ) ( struct ib_device *ibdev,
141
+				    struct ib_queue_pair *qp,
129
 				    struct ib_completion *completion,
142
 				    struct ib_completion *completion,
130
 				    struct io_buffer *iobuf );
143
 				    struct io_buffer *iobuf );
131
 
144
 
156
 	/** Post send work queue entry
169
 	/** Post send work queue entry
157
 	 *
170
 	 *
158
 	 * @v ibdev		Infiniband device
171
 	 * @v ibdev		Infiniband device
159
-	 * @v iobuf		I/O buffer
160
-	 * @v av		Address vector
161
 	 * @v qp		Queue pair
172
 	 * @v qp		Queue pair
173
+	 * @v av		Address vector
174
+	 * @v iobuf		I/O buffer
162
 	 * @ret rc		Return status code
175
 	 * @ret rc		Return status code
163
 	 *
176
 	 *
164
 	 * If this method returns success, the I/O buffer remains
177
 	 * If this method returns success, the I/O buffer remains
167
 	 * interpreted as "failure to enqueue buffer".
180
 	 * interpreted as "failure to enqueue buffer".
168
 	 */
181
 	 */
169
 	int ( * post_send ) ( struct ib_device *ibdev,
182
 	int ( * post_send ) ( struct ib_device *ibdev,
170
-			      struct io_buffer *iobuf,
183
+			      struct ib_queue_pair *qp,
171
 			      struct ib_address_vector *av,
184
 			      struct ib_address_vector *av,
172
-			      struct ib_queue_pair *qp );
185
+			      struct io_buffer *iobuf );
173
 	/** Poll completion queue
186
 	/** Poll completion queue
174
 	 *
187
 	 *
175
 	 * @v ibdev		Infiniband device
188
 	 * @v ibdev		Infiniband device
187
 
200
 
188
 /** An Infiniband device */
201
 /** An Infiniband device */
189
 struct ib_device {	
202
 struct ib_device {	
190
-	/** Driver private data */
191
-	void *priv;
203
+	/** Device private data */
204
+	void *dev_priv;
192
 };
205
 };
193
 
206
 
194
 
207
 
208
+extern struct ib_queue_pair * ib_find_qp ( struct list_head *list,
209
+					   unsigned long qpn );
210
+
195
 
211
 
196
 
212
 
197
 extern struct ll_protocol infiniband_protocol;
213
 extern struct ll_protocol infiniband_protocol;

+ 20
- 0
src/net/infiniband.c View File

33
  *
33
  *
34
  */
34
  */
35
 
35
 
36
+/**
37
+ * Find queue pair from a list
38
+ *
39
+ * @v list		List of queue pairs
40
+ * @v qpn		Queue pair number
41
+ * @ret qp		Queue pair, or NULL if not found
42
+ */
43
+struct ib_queue_pair * ib_find_qp ( struct list_head *list,
44
+				    unsigned long qpn ) {
45
+	struct ib_queue_pair *qp;
46
+
47
+	list_for_each_entry ( qp, list, list ) {
48
+		if ( qp->qpn == qpn )
49
+			return qp;
50
+	}
51
+	return NULL;
52
+}
53
+
54
+
55
+
36
 /** Infiniband broadcast MAC address */
56
 /** Infiniband broadcast MAC address */
37
 static uint8_t ib_broadcast[IB_ALEN] = { 0xff, };
57
 static uint8_t ib_broadcast[IB_ALEN] = { 0xff, };
38
 
58
 

Loading…
Cancel
Save