@@ -70,6 +70,23 @@ struct smc_llc_msg_add_link { /* type 0x02 */
7070 u8 reserved [8 ];
7171};
7272
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+
7390#define SMC_LLC_FLAG_DEL_LINK_ALL 0x40
7491#define SMC_LLC_FLAG_DEL_LINK_ORDERLY 0x20
7592
@@ -121,6 +138,7 @@ struct smc_llc_msg_delete_rkey { /* type 0x09 */
121138union smc_llc_msg {
122139 struct smc_llc_msg_confirm_link confirm_link ;
123140 struct smc_llc_msg_add_link add_link ;
141+ struct smc_llc_msg_add_link_cont add_link_cont ;
124142 struct smc_llc_msg_del_link delete_link ;
125143
126144 struct smc_llc_msg_confirm_rkey confirm_rkey ;
@@ -566,6 +584,137 @@ static int smc_llc_alloc_alt_link(struct smc_link_group *lgr,
566584 return - EMLINK ;
567585}
568586
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+
569718/* prepare and send an add link reject response */
570719static int smc_llc_cli_add_link_reject (struct smc_llc_qentry * qentry )
571720{
@@ -631,7 +780,7 @@ int smc_llc_cli_add_link(struct smc_link *link, struct smc_llc_qentry *qentry)
631780 lnk_new -> gid , lnk_new , SMC_LLC_RESP );
632781 if (rc )
633782 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 );
635784 if (rc ) {
636785 rc = 0 ;
637786 goto out_clear_lnk ;
@@ -794,6 +943,7 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry)
794943 }
795944 return ;
796945 case SMC_LLC_CONFIRM_LINK :
946+ case SMC_LLC_ADD_LINK_CONT :
797947 if (lgr -> llc_flow_lcl .type != SMC_LLC_FLOW_NONE ) {
798948 /* a flow is waiting for this message */
799949 smc_llc_flow_qentry_set (& lgr -> llc_flow_lcl , qentry );
@@ -873,6 +1023,7 @@ static void smc_llc_rx_response(struct smc_link *link,
8731023 break ;
8741024 case SMC_LLC_ADD_LINK :
8751025 case SMC_LLC_CONFIRM_LINK :
1026+ case SMC_LLC_ADD_LINK_CONT :
8761027 case SMC_LLC_CONFIRM_RKEY :
8771028 case SMC_LLC_DELETE_RKEY :
8781029 /* assign responses to the local flow, we requested them */
@@ -1092,6 +1243,10 @@ static struct smc_wr_rx_handler smc_llc_rx_handlers[] = {
10921243 .handler = smc_llc_rx_handler ,
10931244 .type = SMC_LLC_ADD_LINK
10941245 },
1246+ {
1247+ .handler = smc_llc_rx_handler ,
1248+ .type = SMC_LLC_ADD_LINK_CONT
1249+ },
10951250 {
10961251 .handler = smc_llc_rx_handler ,
10971252 .type = SMC_LLC_DELETE_LINK
0 commit comments