|
@@ -12,6 +12,7 @@ Skeleton NIC driver for Etherboot
|
12
|
12
|
|
13
|
13
|
#include <errno.h>
|
14
|
14
|
#include <gpxe/pci.h>
|
|
15
|
+#include <gpxe/malloc.h>
|
15
|
16
|
#include <gpxe/iobuf.h>
|
16
|
17
|
#include <gpxe/netdevice.h>
|
17
|
18
|
#include <gpxe/infiniband.h>
|
|
@@ -266,6 +267,50 @@ static struct net_device_operations mlx_operations = {
|
266
|
267
|
.irq = mlx_irq,
|
267
|
268
|
};
|
268
|
269
|
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+/**
|
|
274
|
+ * Allocate queue number
|
|
275
|
+ *
|
|
276
|
+ * @v q_inuse Queue usage bitmask
|
|
277
|
+ * @v max_inuse Maximum number of in-use queues
|
|
278
|
+ * @ret qn_offset Free queue number offset, or negative error
|
|
279
|
+ */
|
|
280
|
+static int arbel_alloc_qn_offset ( arbel_bitmask_t *q_inuse,
|
|
281
|
+ unsigned int max_inuse ) {
|
|
282
|
+ unsigned int qn_offset = 0;
|
|
283
|
+ arbel_bitmask_t mask = 1;
|
|
284
|
+
|
|
285
|
+ while ( qn_offset < max_inuse ) {
|
|
286
|
+ if ( ( mask & *q_inuse ) == 0 ) {
|
|
287
|
+ *q_inuse |= mask;
|
|
288
|
+ return qn_offset;
|
|
289
|
+ }
|
|
290
|
+ qn_offset++;
|
|
291
|
+ mask <<= 1;
|
|
292
|
+ if ( ! mask ) {
|
|
293
|
+ mask = 1;
|
|
294
|
+ q_inuse++;
|
|
295
|
+ }
|
|
296
|
+ }
|
|
297
|
+ return -ENFILE;
|
|
298
|
+}
|
|
299
|
+
|
|
300
|
+/**
|
|
301
|
+ * Free queue number
|
|
302
|
+ *
|
|
303
|
+ * @v q_inuse Queue usage bitmask
|
|
304
|
+ * @v qn_offset Queue number offset
|
|
305
|
+ */
|
|
306
|
+static void arbel_free_qn_offset ( arbel_bitmask_t *q_inuse, int qn_offset ) {
|
|
307
|
+ arbel_bitmask_t mask;
|
|
308
|
+
|
|
309
|
+ mask = ( 1 << ( qn_offset % ( 8 * sizeof ( mask ) ) ) );
|
|
310
|
+ q_inuse += ( qn_offset / ( 8 * sizeof ( mask ) ) );
|
|
311
|
+ *q_inuse &= ~mask;
|
|
312
|
+}
|
|
313
|
+
|
269
|
314
|
/***************************************************************************
|
270
|
315
|
*
|
271
|
316
|
* HCA commands
|
|
@@ -412,22 +457,78 @@ arbel_cmd_sw2hw_cq ( struct arbel *arbel, unsigned long cqn,
|
412
|
457
|
* @v ibdev Infiniband device
|
413
|
458
|
* @v
|
414
|
459
|
*/
|
415
|
|
-static int arbel_create_cq ( struct ib_device *ibdev,
|
|
460
|
+static int arbel_create_cq ( struct ib_device *ibdev, unsigned int num_cqes,
|
416
|
461
|
struct ib_completion_queue **new_cq ) {
|
417
|
462
|
struct arbel *arbel = ibdev->priv;
|
|
463
|
+ struct arbel_completion_queue *arbel_cq;
|
418
|
464
|
struct arbelprm_completion_queue_context cqctx;
|
419
|
|
- struct ib_completion_queue *cq;
|
|
465
|
+ int cqn_offset;
|
|
466
|
+ unsigned int cqn;
|
|
467
|
+ size_t cqe_size;
|
|
468
|
+ unsigned int i;
|
|
469
|
+ int rc;
|
420
|
470
|
|
421
|
|
- cq = zalloc ( sizeof ( *cq ) );
|
422
|
|
- if ( ! cq )
|
423
|
|
- return -ENOMEM;
|
|
471
|
+ /* Find a free completion queue number */
|
|
472
|
+ cqn_offset = arbel_alloc_qn_offset ( arbel->cq_inuse, ARBEL_MAX_CQS );
|
|
473
|
+ if ( cqn_offset < 0 ) {
|
|
474
|
+ rc = cqn_offset;
|
|
475
|
+ goto err_cqn_offset;
|
|
476
|
+ }
|
|
477
|
+ cqn = ( arbel->limits.reserved_cqs + cqn_offset );
|
424
|
478
|
|
425
|
|
-
|
|
479
|
+ /* Allocate control structures */
|
|
480
|
+ arbel_cq = zalloc ( sizeof ( *arbel_cq ) );
|
|
481
|
+ if ( ! arbel_cq ) {
|
|
482
|
+ rc = -ENOMEM;
|
|
483
|
+ goto err_arbel_cq;
|
|
484
|
+ }
|
|
485
|
+ arbel_cq->cq.cqn = cqn;
|
|
486
|
+ arbel_cq->cq.num_cqes = num_cqes;
|
|
487
|
+ INIT_LIST_HEAD ( &arbel_cq->cq.work_queues );
|
|
488
|
+ arbel_cq->doorbell_idx = arbel_cq_ci_doorbell_idx ( cqn_offset );
|
|
489
|
+
|
|
490
|
+ /* Allocate completion queue itself */
|
|
491
|
+ cqe_size = ( num_cqes * sizeof ( arbel_cq->cqe[0] ) );
|
|
492
|
+ arbel_cq->cqe = malloc_dma ( cqe_size, sizeof ( arbel_cq->cqe[0] ) );
|
|
493
|
+ if ( ! arbel_cq->cqe ) {
|
|
494
|
+ rc = -ENOMEM;
|
|
495
|
+ goto err_cqe;
|
|
496
|
+ }
|
|
497
|
+ memset ( arbel_cq->cqe, 0, cqe_size );
|
|
498
|
+ for ( i = 0 ; i < num_cqes ; i++ ) {
|
|
499
|
+ MLX_FILL_1 ( &arbel_cq->cqe[i].normal, 7, owner, 1 );
|
|
500
|
+ }
|
|
501
|
+ barrier();
|
|
502
|
+
|
|
503
|
+ /* Initialise doorbell records */
|
|
504
|
+ // ...
|
426
|
505
|
|
|
506
|
+ /* Hand queue over to hardware */
|
427
|
507
|
memset ( &cqctx, 0, sizeof ( cqctx ) );
|
428
|
|
-
|
|
508
|
+ MLX_FILL_1 ( &cqctx, 0, st, 0xa /* "Event fired" */ );
|
|
509
|
+ MLX_FILL_1 ( &cqctx, 2, start_address_l,
|
|
510
|
+ virt_to_bus ( arbel_cq->cqe ) );
|
|
511
|
+ /// ....
|
|
512
|
+
|
|
513
|
+ if ( ( rc = arbel_cmd_sw2hw_cq ( arbel, cqn, &cqctx ) ) != 0 ) {
|
|
514
|
+ // ...
|
|
515
|
+ }
|
429
|
516
|
|
430
|
|
- return arbel_cmd_sw2hw_cq ( arbel, 0, &cqctx );
|
|
517
|
+
|
|
518
|
+ // completion queue number
|
|
519
|
+ // doorbell index
|
|
520
|
+
|
|
521
|
+ *new_cq = &arbel_cq->cq;
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+ return 0;
|
|
525
|
+
|
|
526
|
+ err_cqe:
|
|
527
|
+ free ( arbel_cq );
|
|
528
|
+ err_arbel_cq:
|
|
529
|
+ arbel_free_qn_offset ( arbel->cq_inuse, cqn_offset );
|
|
530
|
+ err_cqn_offset:
|
|
531
|
+ return rc;
|
431
|
532
|
}
|
432
|
533
|
|
433
|
534
|
|
|
@@ -764,6 +865,8 @@ static void arbel_remove ( struct pci_device *pci ) {
|
764
|
865
|
static int arbel_probe ( struct pci_device *pci,
|
765
|
866
|
const struct pci_device_id *id __unused ) {
|
766
|
867
|
struct net_device *netdev;
|
|
868
|
+ struct arbelprm_query_dev_lim dev_lim;
|
|
869
|
+ struct arbel *arbel = &static_arbel;
|
767
|
870
|
struct mlx_nic *mlx;
|
768
|
871
|
struct ib_mac *mac;
|
769
|
872
|
udqp_t qph;
|
|
@@ -815,12 +918,14 @@ static int arbel_probe ( struct pci_device *pci,
|
815
|
918
|
list_add ( &static_ipoib_qp.qp.recv.list,
|
816
|
919
|
&static_ipoib_recv_cq.cq.work_queues );
|
817
|
920
|
|
818
|
|
- struct arbelprm_query_dev_lim dev_lim;
|
819
|
|
- memset ( &dev_lim, 0xaa, sizeof ( dev_lim ) );
|
820
|
|
- if ( ( rc = arbel_cmd_query_dev_lim ( &static_arbel,
|
821
|
|
- &dev_lim ) ) != 0 ) {
|
822
|
|
- DBG ( "QUERY_DEV_LIM failed: %s\n", strerror ( rc ) );
|
|
921
|
+ /* Get device limits */
|
|
922
|
+ if ( ( rc = arbel_cmd_query_dev_lim ( arbel, &dev_lim ) ) != 0 ) {
|
|
923
|
+ DBGC ( arbel, "Arbel %p could not get device limits: %s\n",
|
|
924
|
+ arbel, strerror ( rc ) );
|
|
925
|
+ goto err_query_dev_lim;
|
823
|
926
|
}
|
|
927
|
+ arbel->limits.reserved_cqs =
|
|
928
|
+ ( 1 << MLX_GET ( &dev_lim, log2_rsvd_cqs ) );
|
824
|
929
|
DBG ( "Device limits:\n ");
|
825
|
930
|
DBG_HD ( &dev_lim, sizeof ( dev_lim ) );
|
826
|
931
|
|
|
@@ -830,6 +935,7 @@ static int arbel_probe ( struct pci_device *pci,
|
830
|
935
|
|
831
|
936
|
return 0;
|
832
|
937
|
|
|
938
|
+ err_query_dev_lim:
|
833
|
939
|
err_register_netdev:
|
834
|
940
|
err_ipoib_init:
|
835
|
941
|
ib_driver_close ( 0 );
|