@@ -70,6 +70,23 @@ struct smc_llc_msg_add_link { /* type 0x02 */
70
70
u8 reserved [8 ];
71
71
};
72
72
73
+ struct smc_llc_msg_add_link_cont_rt {
74
+ __be32 rmb_key ;
75
+ __be32 rmb_key_new ;
76
+ __be64 rmb_vaddr_new ;
77
+ };
78
+
79
+ #define SMC_LLC_RKEYS_PER_CONT_MSG 2
80
+
81
+ struct smc_llc_msg_add_link_cont { /* type 0x03 */
82
+ struct smc_llc_hdr hd ;
83
+ u8 link_num ;
84
+ u8 num_rkeys ;
85
+ u8 reserved2 [2 ];
86
+ struct smc_llc_msg_add_link_cont_rt rt [SMC_LLC_RKEYS_PER_CONT_MSG ];
87
+ u8 reserved [4 ];
88
+ } __packed ; /* format defined in RFC7609 */
89
+
73
90
#define SMC_LLC_FLAG_DEL_LINK_ALL 0x40
74
91
#define SMC_LLC_FLAG_DEL_LINK_ORDERLY 0x20
75
92
@@ -121,6 +138,7 @@ struct smc_llc_msg_delete_rkey { /* type 0x09 */
121
138
union smc_llc_msg {
122
139
struct smc_llc_msg_confirm_link confirm_link ;
123
140
struct smc_llc_msg_add_link add_link ;
141
+ struct smc_llc_msg_add_link_cont add_link_cont ;
124
142
struct smc_llc_msg_del_link delete_link ;
125
143
126
144
struct smc_llc_msg_confirm_rkey confirm_rkey ;
@@ -566,6 +584,137 @@ static int smc_llc_alloc_alt_link(struct smc_link_group *lgr,
566
584
return - EMLINK ;
567
585
}
568
586
587
+ /* return first buffer from any of the next buf lists */
588
+ static struct smc_buf_desc * _smc_llc_get_next_rmb (struct smc_link_group * lgr ,
589
+ int * buf_lst )
590
+ {
591
+ struct smc_buf_desc * buf_pos ;
592
+
593
+ while (* buf_lst < SMC_RMBE_SIZES ) {
594
+ buf_pos = list_first_entry_or_null (& lgr -> rmbs [* buf_lst ],
595
+ struct smc_buf_desc , list );
596
+ if (buf_pos )
597
+ return buf_pos ;
598
+ (* buf_lst )++ ;
599
+ }
600
+ return NULL ;
601
+ }
602
+
603
+ /* return next rmb from buffer lists */
604
+ static struct smc_buf_desc * smc_llc_get_next_rmb (struct smc_link_group * lgr ,
605
+ int * buf_lst ,
606
+ struct smc_buf_desc * buf_pos )
607
+ {
608
+ struct smc_buf_desc * buf_next ;
609
+
610
+ if (!buf_pos || list_is_last (& buf_pos -> list , & lgr -> rmbs [* buf_lst ])) {
611
+ (* buf_lst )++ ;
612
+ return _smc_llc_get_next_rmb (lgr , buf_lst );
613
+ }
614
+ buf_next = list_next_entry (buf_pos , list );
615
+ return buf_next ;
616
+ }
617
+
618
+ static struct smc_buf_desc * smc_llc_get_first_rmb (struct smc_link_group * lgr ,
619
+ int * buf_lst )
620
+ {
621
+ * buf_lst = 0 ;
622
+ return smc_llc_get_next_rmb (lgr , buf_lst , NULL );
623
+ }
624
+
625
+ /* send one add_link_continue msg */
626
+ static int smc_llc_add_link_cont (struct smc_link * link ,
627
+ struct smc_link * link_new , u8 * num_rkeys_todo ,
628
+ int * buf_lst , struct smc_buf_desc * * buf_pos )
629
+ {
630
+ struct smc_llc_msg_add_link_cont * addc_llc ;
631
+ struct smc_link_group * lgr = link -> lgr ;
632
+ int prim_lnk_idx , lnk_idx , i , rc ;
633
+ struct smc_wr_tx_pend_priv * pend ;
634
+ struct smc_wr_buf * wr_buf ;
635
+ struct smc_buf_desc * rmb ;
636
+ u8 n ;
637
+
638
+ rc = smc_llc_add_pending_send (link , & wr_buf , & pend );
639
+ if (rc )
640
+ return rc ;
641
+ addc_llc = (struct smc_llc_msg_add_link_cont * )wr_buf ;
642
+ memset (addc_llc , 0 , sizeof (* addc_llc ));
643
+
644
+ prim_lnk_idx = link -> link_idx ;
645
+ lnk_idx = link_new -> link_idx ;
646
+ addc_llc -> link_num = link_new -> link_id ;
647
+ addc_llc -> num_rkeys = * num_rkeys_todo ;
648
+ n = * num_rkeys_todo ;
649
+ for (i = 0 ; i < min_t (u8 , n , SMC_LLC_RKEYS_PER_CONT_MSG ); i ++ ) {
650
+ if (!* buf_pos ) {
651
+ addc_llc -> num_rkeys = addc_llc -> num_rkeys -
652
+ * num_rkeys_todo ;
653
+ * num_rkeys_todo = 0 ;
654
+ break ;
655
+ }
656
+ rmb = * buf_pos ;
657
+
658
+ addc_llc -> rt [i ].rmb_key = htonl (rmb -> mr_rx [prim_lnk_idx ]-> rkey );
659
+ addc_llc -> rt [i ].rmb_key_new = htonl (rmb -> mr_rx [lnk_idx ]-> rkey );
660
+ addc_llc -> rt [i ].rmb_vaddr_new =
661
+ cpu_to_be64 ((u64 )sg_dma_address (rmb -> sgt [lnk_idx ].sgl ));
662
+
663
+ (* num_rkeys_todo )-- ;
664
+ * buf_pos = smc_llc_get_next_rmb (lgr , buf_lst , * buf_pos );
665
+ while (* buf_pos && !(* buf_pos )-> used )
666
+ * buf_pos = smc_llc_get_next_rmb (lgr , buf_lst , * buf_pos );
667
+ }
668
+ addc_llc -> hd .common .type = SMC_LLC_ADD_LINK_CONT ;
669
+ addc_llc -> hd .length = sizeof (struct smc_llc_msg_add_link_cont );
670
+ if (lgr -> role == SMC_CLNT )
671
+ addc_llc -> hd .flags |= SMC_LLC_FLAG_RESP ;
672
+ return smc_wr_tx_send (link , pend );
673
+ }
674
+
675
+ static int smc_llc_cli_rkey_exchange (struct smc_link * link ,
676
+ struct smc_link * link_new )
677
+ {
678
+ struct smc_llc_msg_add_link_cont * addc_llc ;
679
+ struct smc_link_group * lgr = link -> lgr ;
680
+ u8 max , num_rkeys_send , num_rkeys_recv ;
681
+ struct smc_llc_qentry * qentry ;
682
+ struct smc_buf_desc * buf_pos ;
683
+ int buf_lst ;
684
+ int rc = 0 ;
685
+ int i ;
686
+
687
+ mutex_lock (& lgr -> rmbs_lock );
688
+ num_rkeys_send = lgr -> conns_num ;
689
+ buf_pos = smc_llc_get_first_rmb (lgr , & buf_lst );
690
+ do {
691
+ qentry = smc_llc_wait (lgr , NULL , SMC_LLC_WAIT_TIME ,
692
+ SMC_LLC_ADD_LINK_CONT );
693
+ if (!qentry ) {
694
+ rc = - ETIMEDOUT ;
695
+ break ;
696
+ }
697
+ addc_llc = & qentry -> msg .add_link_cont ;
698
+ num_rkeys_recv = addc_llc -> num_rkeys ;
699
+ max = min_t (u8 , num_rkeys_recv , SMC_LLC_RKEYS_PER_CONT_MSG );
700
+ for (i = 0 ; i < max ; i ++ ) {
701
+ smc_rtoken_set (lgr , link -> link_idx , link_new -> link_idx ,
702
+ addc_llc -> rt [i ].rmb_key ,
703
+ addc_llc -> rt [i ].rmb_vaddr_new ,
704
+ addc_llc -> rt [i ].rmb_key_new );
705
+ num_rkeys_recv -- ;
706
+ }
707
+ smc_llc_flow_qentry_del (& lgr -> llc_flow_lcl );
708
+ rc = smc_llc_add_link_cont (link , link_new , & num_rkeys_send ,
709
+ & buf_lst , & buf_pos );
710
+ if (rc )
711
+ break ;
712
+ } while (num_rkeys_send || num_rkeys_recv );
713
+
714
+ mutex_unlock (& lgr -> rmbs_lock );
715
+ return rc ;
716
+ }
717
+
569
718
/* prepare and send an add link reject response */
570
719
static int smc_llc_cli_add_link_reject (struct smc_llc_qentry * qentry )
571
720
{
@@ -631,7 +780,7 @@ int smc_llc_cli_add_link(struct smc_link *link, struct smc_llc_qentry *qentry)
631
780
lnk_new -> gid , lnk_new , SMC_LLC_RESP );
632
781
if (rc )
633
782
goto out_clear_lnk ;
634
- /* tbd: rc = smc_llc_cli_rkey_exchange(link, lnk_new); */
783
+ rc = smc_llc_cli_rkey_exchange (link , lnk_new );
635
784
if (rc ) {
636
785
rc = 0 ;
637
786
goto out_clear_lnk ;
@@ -794,6 +943,7 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
794
943
}
795
944
return ;
796
945
case SMC_LLC_CONFIRM_LINK :
946
+ case SMC_LLC_ADD_LINK_CONT :
797
947
if (lgr -> llc_flow_lcl .type != SMC_LLC_FLOW_NONE ) {
798
948
/* a flow is waiting for this message */
799
949
smc_llc_flow_qentry_set (& lgr -> llc_flow_lcl , qentry );
@@ -873,6 +1023,7 @@ static void smc_llc_rx_response(struct smc_link *link,
873
1023
break ;
874
1024
case SMC_LLC_ADD_LINK :
875
1025
case SMC_LLC_CONFIRM_LINK :
1026
+ case SMC_LLC_ADD_LINK_CONT :
876
1027
case SMC_LLC_CONFIRM_RKEY :
877
1028
case SMC_LLC_DELETE_RKEY :
878
1029
/* assign responses to the local flow, we requested them */
@@ -1092,6 +1243,10 @@ static struct smc_wr_rx_handler smc_llc_rx_handlers[] = {
1092
1243
.handler = smc_llc_rx_handler ,
1093
1244
.type = SMC_LLC_ADD_LINK
1094
1245
},
1246
+ {
1247
+ .handler = smc_llc_rx_handler ,
1248
+ .type = SMC_LLC_ADD_LINK_CONT
1249
+ },
1095
1250
{
1096
1251
.handler = smc_llc_rx_handler ,
1097
1252
.type = SMC_LLC_DELETE_LINK
0 commit comments