|
@@ -464,6 +464,40 @@ arbel_cmd_hw2sw_cq ( struct arbel *arbel, unsigned long cqn ) {
|
464
|
464
|
1, NULL, cqn, NULL );
|
465
|
465
|
}
|
466
|
466
|
|
|
467
|
+static inline int
|
|
468
|
+arbel_cmd_rst2init_qpee ( struct arbel *arbel, unsigned long qpn,
|
|
469
|
+ struct arbelprm_queue_pair_ee_context_entry *ctx ) {
|
|
470
|
+ return arbel_cmd ( arbel,
|
|
471
|
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_RST2INIT_QPEE,
|
|
472
|
+ 1, sizeof ( *ctx ) ),
|
|
473
|
+ 0, ctx, qpn, NULL );
|
|
474
|
+}
|
|
475
|
+
|
|
476
|
+static inline int
|
|
477
|
+arbel_cmd_init2rtr_qpee ( struct arbel *arbel, unsigned long qpn,
|
|
478
|
+ struct arbelprm_queue_pair_ee_context_entry *ctx ) {
|
|
479
|
+ return arbel_cmd ( arbel,
|
|
480
|
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_INIT2RTR_QPEE,
|
|
481
|
+ 1, sizeof ( *ctx ) ),
|
|
482
|
+ 0, ctx, qpn, NULL );
|
|
483
|
+}
|
|
484
|
+
|
|
485
|
+static inline int
|
|
486
|
+arbel_cmd_rtr2rts_qpee ( struct arbel *arbel, unsigned long qpn,
|
|
487
|
+ struct arbelprm_queue_pair_ee_context_entry *ctx ) {
|
|
488
|
+ return arbel_cmd ( arbel,
|
|
489
|
+ ARBEL_HCR_IN_CMD ( ARBEL_HCR_RTR2RTS_QPEE,
|
|
490
|
+ 1, sizeof ( *ctx ) ),
|
|
491
|
+ 0, ctx, qpn, NULL );
|
|
492
|
+}
|
|
493
|
+
|
|
494
|
+static inline int
|
|
495
|
+arbel_cmd_2rst_qpee ( struct arbel *arbel, unsigned long qpn ) {
|
|
496
|
+ return arbel_cmd ( arbel,
|
|
497
|
+ ARBEL_HCR_VOID_CMD ( ARBEL_HCR_2RST_QPEE ),
|
|
498
|
+ 0x03, NULL, qpn, NULL );
|
|
499
|
+}
|
|
500
|
+
|
467
|
501
|
/***************************************************************************
|
468
|
502
|
*
|
469
|
503
|
* Completion queue operations
|
|
@@ -486,7 +520,6 @@ static int arbel_create_cq ( struct ib_device *ibdev,
|
486
|
520
|
struct arbelprm_cq_ci_db_record *ci_db_rec;
|
487
|
521
|
struct arbelprm_cq_arm_db_record *arm_db_rec;
|
488
|
522
|
int cqn_offset;
|
489
|
|
- size_t cqe_size;
|
490
|
523
|
unsigned int i;
|
491
|
524
|
int rc;
|
492
|
525
|
|
|
@@ -509,13 +542,14 @@ static int arbel_create_cq ( struct ib_device *ibdev,
|
509
|
542
|
arbel_cq->arm_doorbell_idx = arbel_cq_arm_doorbell_idx ( cqn_offset );
|
510
|
543
|
|
511
|
544
|
/* Allocate completion queue itself */
|
512
|
|
- cqe_size = ( cq->num_cqes * sizeof ( arbel_cq->cqe[0] ) );
|
513
|
|
- arbel_cq->cqe = malloc_dma ( cqe_size, sizeof ( arbel_cq->cqe[0] ) );
|
|
545
|
+ arbel_cq->cqe_size = ( cq->num_cqes * sizeof ( arbel_cq->cqe[0] ) );
|
|
546
|
+ arbel_cq->cqe = malloc_dma ( arbel_cq->cqe_size,
|
|
547
|
+ sizeof ( arbel_cq->cqe[0] ) );
|
514
|
548
|
if ( ! arbel_cq->cqe ) {
|
515
|
549
|
rc = -ENOMEM;
|
516
|
550
|
goto err_cqe;
|
517
|
551
|
}
|
518
|
|
- memset ( arbel_cq->cqe, 0, cqe_size );
|
|
552
|
+ memset ( arbel_cq->cqe, 0, arbel_cq->cqe_size );
|
519
|
553
|
for ( i = 0 ; i < cq->num_cqes ; i++ ) {
|
520
|
554
|
MLX_FILL_1 ( &arbel_cq->cqe[i].normal, 7, owner, 1 );
|
521
|
555
|
}
|
|
@@ -538,11 +572,9 @@ static int arbel_create_cq ( struct ib_device *ibdev,
|
538
|
572
|
MLX_FILL_1 ( &cqctx, 0, st, 0xa /* "Event fired" */ );
|
539
|
573
|
MLX_FILL_1 ( &cqctx, 2, start_address_l,
|
540
|
574
|
virt_to_bus ( arbel_cq->cqe ) );
|
541
|
|
-#if 0
|
542
|
575
|
MLX_FILL_2 ( &cqctx, 3,
|
543
|
576
|
usr_page, arbel->limits.reserved_uars,
|
544
|
|
- log_cq_size, log2_num_cqes );
|
545
|
|
-#endif
|
|
577
|
+ log_cq_size, ( fls ( cq->num_cqes ) - 1 ) );
|
546
|
578
|
MLX_FILL_1 ( &cqctx, 5, c_eqn, arbel->eqn );
|
547
|
579
|
MLX_FILL_1 ( &cqctx, 6, pd, ARBEL_GLOBAL_PD );
|
548
|
580
|
MLX_FILL_1 ( &cqctx, 7, l_key, arbel->reserved_lkey );
|
|
@@ -554,16 +586,16 @@ static int arbel_create_cq ( struct ib_device *ibdev,
|
554
|
586
|
if ( ( rc = arbel_cmd_sw2hw_cq ( arbel, cq->cqn, &cqctx ) ) != 0 ) {
|
555
|
587
|
DBGC ( arbel, "Arbel %p SW2HW_CQ failed: %s\n",
|
556
|
588
|
arbel, strerror ( rc ) );
|
557
|
|
- goto err_sw2hw;
|
|
589
|
+ goto err_sw2hw_cq;
|
558
|
590
|
}
|
559
|
591
|
|
560
|
592
|
cq->dev_priv = arbel_cq;
|
561
|
593
|
return 0;
|
562
|
594
|
|
563
|
|
- err_sw2hw:
|
|
595
|
+ err_sw2hw_cq:
|
564
|
596
|
MLX_FILL_1 ( ci_db_rec, 1, res, ARBEL_UAR_RES_NONE );
|
565
|
597
|
MLX_FILL_1 ( arm_db_rec, 1, res, ARBEL_UAR_RES_NONE );
|
566
|
|
- free_dma ( arbel_cq->cqe, cqe_size );
|
|
598
|
+ free_dma ( arbel_cq->cqe, arbel_cq->cqe_size );
|
567
|
599
|
err_cqe:
|
568
|
600
|
free ( arbel_cq );
|
569
|
601
|
err_arbel_cq:
|
|
@@ -585,35 +617,31 @@ static void arbel_destroy_cq ( struct ib_device *ibdev,
|
585
|
617
|
struct arbelprm_cq_ci_db_record *ci_db_rec;
|
586
|
618
|
struct arbelprm_cq_arm_db_record *arm_db_rec;
|
587
|
619
|
int cqn_offset;
|
588
|
|
- size_t cqe_size;
|
589
|
|
- unsigned int ci_doorbell_idx;
|
590
|
|
- unsigned int arm_doorbell_idx;
|
591
|
620
|
int rc;
|
592
|
621
|
|
593
|
|
- assert ( list_empty ( &cq->work_queues ) );
|
594
|
|
-
|
595
|
622
|
/* Take ownership back from hardware */
|
596
|
623
|
if ( ( rc = arbel_cmd_hw2sw_cq ( arbel, cq->cqn ) ) != 0 ) {
|
597
|
|
- DBGC ( arbel, "Arbel %p FATAL HW2SW_CQ failed: %s\n",
|
598
|
|
- arbel, strerror ( rc ) );
|
|
624
|
+ DBGC ( arbel, "Arbel %p FATAL HW2SW_CQ failed on CQN %#lx: "
|
|
625
|
+ "%s\n", arbel, cq->cqn, strerror ( rc ) );
|
599
|
626
|
/* Leak memory and return; at least we avoid corruption */
|
600
|
627
|
return;
|
601
|
628
|
}
|
602
|
629
|
|
603
|
630
|
/* Clear doorbell records */
|
604
|
|
- cqn_offset = ( cq->cqn - arbel->limits.reserved_cqs );
|
605
|
|
- ci_doorbell_idx = arbel_cq_ci_doorbell_idx ( cqn_offset );
|
606
|
|
- arm_doorbell_idx = arbel_cq_arm_doorbell_idx ( cqn_offset );
|
607
|
|
- ci_db_rec = &arbel->db_rec[ci_doorbell_idx].cq_ci;
|
608
|
|
- arm_db_rec = &arbel->db_rec[arm_doorbell_idx].cq_arm;
|
|
631
|
+ ci_db_rec = &arbel->db_rec[arbel_cq->ci_doorbell_idx].cq_ci;
|
|
632
|
+ arm_db_rec = &arbel->db_rec[arbel_cq->arm_doorbell_idx].cq_arm;
|
609
|
633
|
MLX_FILL_1 ( ci_db_rec, 1, res, ARBEL_UAR_RES_NONE );
|
610
|
634
|
MLX_FILL_1 ( arm_db_rec, 1, res, ARBEL_UAR_RES_NONE );
|
611
|
635
|
|
612
|
636
|
/* Free memory */
|
613
|
|
- cqe_size = ( cq->num_cqes * sizeof ( arbel_cq->cqe[0] ) );
|
614
|
|
- free_dma ( arbel_cq->cqe, cqe_size );
|
|
637
|
+ free_dma ( arbel_cq->cqe, arbel_cq->cqe_size );
|
615
|
638
|
free ( arbel_cq );
|
|
639
|
+
|
|
640
|
+ /* Mark queue number as free */
|
|
641
|
+ cqn_offset = ( cq->cqn - arbel->limits.reserved_cqs );
|
616
|
642
|
arbel_free_qn_offset ( arbel->cq_inuse, cqn_offset );
|
|
643
|
+
|
|
644
|
+ cq->dev_priv = NULL;
|
617
|
645
|
}
|
618
|
646
|
|
619
|
647
|
/***************************************************************************
|
|
@@ -623,22 +651,50 @@ static void arbel_destroy_cq ( struct ib_device *ibdev,
|
623
|
651
|
***************************************************************************
|
624
|
652
|
*/
|
625
|
653
|
|
|
654
|
+static int arbel_create_send_wq ( struct arbel_send_work_queue *arbel_send_wq,
|
|
655
|
+ unsigned int num_wqes ) {
|
|
656
|
+
|
|
657
|
+ arbel_send_wq->wqe_size = ( num_wqes *
|
|
658
|
+ sizeof ( arbel_send_wq->wqe[0] ) );
|
|
659
|
+ arbel_send_wq->wqe = malloc_dma ( arbel_send_wq->wqe_size,
|
|
660
|
+ sizeof ( arbel_send_wq->wqe[0] ) );
|
|
661
|
+ if ( ! arbel_send_wq->wqe )
|
|
662
|
+ return -ENOMEM;
|
|
663
|
+
|
|
664
|
+ // initialise (prelink?)
|
|
665
|
+}
|
|
666
|
+
|
|
667
|
+static int arbel_create_recv_wq ( struct arbel_recv_work_queue *arbel_recv_wq,
|
|
668
|
+ unsigned int num_wqes ) {
|
|
669
|
+
|
|
670
|
+ arbel_recv_wq->wqe_size = ( num_wqes *
|
|
671
|
+ sizeof ( arbel_recv_wq->wqe[0] ) );
|
|
672
|
+ arbel_recv_wq->wqe = malloc_dma ( arbel_recv_wq->wqe_size,
|
|
673
|
+ sizeof ( arbel_recv_wq->wqe[0] ) );
|
|
674
|
+ if ( ! arbel_recv_wq->wqe )
|
|
675
|
+ return -ENOMEM;
|
|
676
|
+
|
|
677
|
+ // initialise (prelink?)
|
|
678
|
+}
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+/**
|
|
684
|
+ * Create queue pair
|
|
685
|
+ *
|
|
686
|
+ * @v ibdev Infiniband device
|
|
687
|
+ * @v qp Queue pair
|
|
688
|
+ * @ret rc Return status code
|
|
689
|
+ */
|
626
|
690
|
static int arbel_create_qp ( struct ib_device *ibdev,
|
627
|
|
- unsigned int log2_num_send_wqes,
|
628
|
|
- struct ib_completion_queue *send_cq,
|
629
|
|
- unsigned int log2_num_recv_wqes,
|
630
|
|
- struct ib_completion_queue *recv_cq,
|
631
|
|
- struct ib_queue_pair **new_qp ) {
|
|
691
|
+ struct ib_queue_pair *qp ) {
|
632
|
692
|
struct arbel *arbel = ibdev->dev_priv;
|
633
|
693
|
struct arbel_queue_pair *arbel_qp;
|
|
694
|
+ struct arbelprm_queue_pair_ee_context_entry qpctx;
|
634
|
695
|
struct arbelprm_qp_db_record *send_db_rec;
|
635
|
696
|
struct arbelprm_qp_db_record *recv_db_rec;
|
636
|
697
|
int qpn_offset;
|
637
|
|
- unsigned int qpn;
|
638
|
|
- unsigned int num_send_wqes;
|
639
|
|
- unsigned int num_recv_wqes;
|
640
|
|
- unsigned int send_doorbell_idx;
|
641
|
|
- unsigned int recv_doorbell_idx;
|
642
|
698
|
int rc;
|
643
|
699
|
|
644
|
700
|
/* Find a free queue pair number */
|
|
@@ -648,21 +704,117 @@ static int arbel_create_qp ( struct ib_device *ibdev,
|
648
|
704
|
rc = qpn_offset;
|
649
|
705
|
goto err_qpn_offset;
|
650
|
706
|
}
|
651
|
|
- qpn = ( ARBEL_QPN_BASE + arbel->limits.reserved_qps + qpn_offset );
|
652
|
|
- send_doorbell_idx = arbel_send_doorbell_idx ( qpn_offset );
|
653
|
|
- recv_doorbell_idx = arbel_recv_doorbell_idx ( qpn_offset );
|
|
707
|
+ qp->qpn = ( ARBEL_QPN_BASE + arbel->limits.reserved_qps + qpn_offset );
|
654
|
708
|
|
655
|
709
|
/* Allocate control structures */
|
656
|
|
- num_send_wqes = ( 1 << log2_num_send_wqes );
|
657
|
|
- num_recv_wqes = ( 1 << log2_num_recv_wqes );
|
658
|
710
|
arbel_qp = zalloc ( sizeof ( *arbel_qp ) );
|
|
711
|
+ if ( ! arbel_qp ) {
|
|
712
|
+ rc = -ENOMEM;
|
|
713
|
+ goto err_arbel_qp;
|
|
714
|
+ }
|
|
715
|
+ arbel_qp->send.doorbell_idx = arbel_send_doorbell_idx ( qpn_offset );
|
|
716
|
+ arbel_qp->recv.doorbell_idx = arbel_recv_doorbell_idx ( qpn_offset );
|
|
717
|
+
|
|
718
|
+ /* Create send and receive work queues */
|
|
719
|
+ if ( ( rc = arbel_create_send_wq ( &arbel_qp->send,
|
|
720
|
+ qp->send.num_wqes ) ) != 0 )
|
|
721
|
+ goto err_create_send_wq;
|
|
722
|
+ if ( ( rc = arbel_create_recv_wq ( &arbel_qp->recv,
|
|
723
|
+ qp->recv.num_wqes ) ) != 0 )
|
|
724
|
+ goto err_create_recv_wq;
|
|
725
|
+
|
|
726
|
+ /* Initialise doorbell records */
|
|
727
|
+ send_db_rec = &arbel->db_rec[arbel_qp->send.doorbell_idx].qp;
|
|
728
|
+ MLX_FILL_1 ( send_db_rec, 0, counter, 0 );
|
|
729
|
+ MLX_FILL_2 ( send_db_rec, 1,
|
|
730
|
+ res, ARBEL_UAR_RES_SQ,
|
|
731
|
+ qp_number, qp->qpn );
|
|
732
|
+ recv_db_rec = &arbel->db_rec[arbel_qp->recv.doorbell_idx].qp;
|
|
733
|
+ MLX_FILL_1 ( recv_db_rec, 0, counter, 0 );
|
|
734
|
+ MLX_FILL_2 ( recv_db_rec, 1,
|
|
735
|
+ res, ARBEL_UAR_RES_RQ,
|
|
736
|
+ qp_number, qp->qpn );
|
|
737
|
+
|
|
738
|
+ /* Hand queue over to hardware */
|
|
739
|
+ memset ( &qpctx, 0, sizeof ( qpctx ) );
|
|
740
|
+ // ... fill in context
|
|
741
|
+ if ( ( rc = arbel_cmd_rst2init_qpee ( arbel, qp->qpn, &qpctx )) != 0 ){
|
|
742
|
+ DBGC ( arbel, "Arbel %p RST2INIT_QPEE failed: %s\n",
|
|
743
|
+ arbel, strerror ( rc ) );
|
|
744
|
+ goto err_rst2init_qpee;
|
|
745
|
+ }
|
|
746
|
+ if ( ( rc = arbel_cmd_init2rtr_qpee ( arbel, qp->qpn, &qpctx )) != 0 ){
|
|
747
|
+ DBGC ( arbel, "Arbel %p INIT2RTR_QPEE failed: %s\n",
|
|
748
|
+ arbel, strerror ( rc ) );
|
|
749
|
+ goto err_init2rtr_qpee;
|
|
750
|
+ }
|
|
751
|
+ if ( ( rc = arbel_cmd_rtr2rts_qpee ( arbel, qp->qpn, &qpctx ) ) != 0 ){
|
|
752
|
+ DBGC ( arbel, "Arbel %p RTR2RTS_QPEE failed: %s\n",
|
|
753
|
+ arbel, strerror ( rc ) );
|
|
754
|
+ goto err_rtr2rts_qpee;
|
|
755
|
+ }
|
659
|
756
|
|
|
757
|
+ qp->dev_priv = arbel_qp;
|
660
|
758
|
return 0;
|
661
|
759
|
|
|
760
|
+ err_rtr2rts_qpee:
|
|
761
|
+ err_init2rtr_qpee:
|
|
762
|
+ arbel_cmd_2rst_qpee ( arbel, qp->qpn );
|
|
763
|
+ err_rst2init_qpee:
|
|
764
|
+ MLX_FILL_1 ( send_db_rec, 1, res, ARBEL_UAR_RES_NONE );
|
|
765
|
+ MLX_FILL_1 ( recv_db_rec, 1, res, ARBEL_UAR_RES_NONE );
|
|
766
|
+ free_dma ( arbel_qp->recv.wqe, arbel_qp->recv.wqe_size );
|
|
767
|
+ err_create_recv_wq:
|
|
768
|
+ free_dma ( arbel_qp->send.wqe, arbel_qp->send.wqe_size );
|
|
769
|
+ err_create_send_wq:
|
|
770
|
+ free ( arbel_qp );
|
|
771
|
+ err_arbel_qp:
|
|
772
|
+ arbel_free_qn_offset ( arbel->qp_inuse, qpn_offset );
|
662
|
773
|
err_qpn_offset:
|
663
|
774
|
return rc;
|
664
|
775
|
}
|
665
|
776
|
|
|
777
|
+/**
|
|
778
|
+ * Destroy queue pair
|
|
779
|
+ *
|
|
780
|
+ * @v ibdev Infiniband device
|
|
781
|
+ * @v qp Queue pair
|
|
782
|
+ */
|
|
783
|
+static void arbel_destroy_qp ( struct ib_device *ibdev,
|
|
784
|
+ struct ib_queue_pair *qp ) {
|
|
785
|
+ struct arbel *arbel = ibdev->dev_priv;
|
|
786
|
+ struct arbel_queue_pair *arbel_qp = qp->dev_priv;
|
|
787
|
+ struct arbelprm_qp_db_record *send_db_rec;
|
|
788
|
+ struct arbelprm_qp_db_record *recv_db_rec;
|
|
789
|
+ int qpn_offset;
|
|
790
|
+ int rc;
|
|
791
|
+
|
|
792
|
+ /* Take ownership back from hardware */
|
|
793
|
+ if ( ( rc = arbel_cmd_2rst_qpee ( arbel, qp->qpn ) ) != 0 ) {
|
|
794
|
+ DBGC ( arbel, "Arbel %p FATAL 2RST_QPEE failed on QPN %#lx: "
|
|
795
|
+ "%s\n", arbel, qp->qpn, strerror ( rc ) );
|
|
796
|
+ /* Leak memory and return; at least we avoid corruption */
|
|
797
|
+ return;
|
|
798
|
+ }
|
|
799
|
+
|
|
800
|
+ /* Clear doorbell records */
|
|
801
|
+ send_db_rec = &arbel->db_rec[arbel_qp->send.doorbell_idx].qp;
|
|
802
|
+ recv_db_rec = &arbel->db_rec[arbel_qp->recv.doorbell_idx].qp;
|
|
803
|
+ MLX_FILL_1 ( send_db_rec, 1, res, ARBEL_UAR_RES_NONE );
|
|
804
|
+ MLX_FILL_1 ( recv_db_rec, 1, res, ARBEL_UAR_RES_NONE );
|
|
805
|
+
|
|
806
|
+ /* Free memory */
|
|
807
|
+ free_dma ( arbel_qp->send.wqe, arbel_qp->send.wqe_size );
|
|
808
|
+ free_dma ( arbel_qp->recv.wqe, arbel_qp->recv.wqe_size );
|
|
809
|
+ free ( arbel_qp );
|
|
810
|
+
|
|
811
|
+ /* Mark queue number as free */
|
|
812
|
+ qpn_offset = ( qp->qpn - ARBEL_QPN_BASE - arbel->limits.reserved_qps );
|
|
813
|
+ arbel_free_qn_offset ( arbel->qp_inuse, qpn_offset );
|
|
814
|
+
|
|
815
|
+ qp->dev_priv = NULL;
|
|
816
|
+}
|
|
817
|
+
|
666
|
818
|
/***************************************************************************
|
667
|
819
|
*
|
668
|
820
|
* Work request operations
|
|
@@ -966,6 +1118,8 @@ static void arbel_poll_cq ( struct ib_device *ibdev,
|
966
|
1118
|
static struct ib_device_operations arbel_ib_operations = {
|
967
|
1119
|
.create_cq = arbel_create_cq,
|
968
|
1120
|
.destroy_cq = arbel_destroy_cq,
|
|
1121
|
+ .create_qp = arbel_create_qp,
|
|
1122
|
+ .destroy_qp = arbel_destroy_qp,
|
969
|
1123
|
.post_send = arbel_post_send,
|
970
|
1124
|
.post_recv = arbel_post_recv,
|
971
|
1125
|
.poll_cq = arbel_poll_cq,
|
|
@@ -1048,6 +1202,7 @@ static int arbel_probe ( struct pci_device *pci,
|
1048
|
1202
|
&static_ipoib_send_cq.work_queues );
|
1049
|
1203
|
list_add ( &static_ipoib_qp.recv.list,
|
1050
|
1204
|
&static_ipoib_recv_cq.work_queues );
|
|
1205
|
+ static_ibdev.op = &arbel_ib_operations;
|
1051
|
1206
|
|
1052
|
1207
|
/* Get device limits */
|
1053
|
1208
|
if ( ( rc = arbel_cmd_query_dev_lim ( arbel, &dev_lim ) ) != 0 ) {
|