@@ -1014,7 +1014,8 @@ static int smc_find_ism_v2_device_clnt(struct smc_sock *smc,
10141014{
10151015 int rc = SMC_CLC_DECL_NOSMCDDEV ;
10161016 struct smcd_dev * smcd ;
1017- int i = 1 ;
1017+ int i = 1 , entry = 1 ;
1018+ bool is_virtual ;
10181019 u16 chid ;
10191020
10201021 if (smcd_indicated (ini -> smc_type_v1 ))
@@ -1026,14 +1027,23 @@ static int smc_find_ism_v2_device_clnt(struct smc_sock *smc,
10261027 chid = smc_ism_get_chid (smcd );
10271028 if (!smc_find_ism_v2_is_unique_chid (chid , ini , i ))
10281029 continue ;
1030+ is_virtual = __smc_ism_is_virtual (chid );
10291031 if (!smc_pnet_is_pnetid_set (smcd -> pnetid ) ||
10301032 smc_pnet_is_ndev_pnetid (sock_net (& smc -> sk ), smcd -> pnetid )) {
1033+ if (is_virtual && entry == SMCD_CLC_MAX_V2_GID_ENTRIES )
1034+ /* It's the last GID-CHID entry left in CLC
1035+ * Proposal SMC-Dv2 extension, but a virtual
1036+ * ISM device will take two entries. So give
1037+ * up it and try the next potential ISM device.
1038+ */
1039+ continue ;
10311040 ini -> ism_dev [i ] = smcd ;
10321041 ini -> ism_chid [i ] = chid ;
10331042 ini -> is_smcd = true;
10341043 rc = 0 ;
10351044 i ++ ;
1036- if (i > SMC_MAX_ISM_DEVS )
1045+ entry = is_virtual ? entry + 2 : entry + 1 ;
1046+ if (entry > SMCD_CLC_MAX_V2_GID_ENTRIES )
10371047 break ;
10381048 }
10391049 }
@@ -1375,8 +1385,13 @@ static int smc_connect_ism(struct smc_sock *smc,
13751385 rc = smc_v2_determine_accepted_chid (aclc , ini );
13761386 if (rc )
13771387 return rc ;
1388+
1389+ if (__smc_ism_is_virtual (ini -> ism_chid [ini -> ism_selected ]))
1390+ ini -> ism_peer_gid [ini -> ism_selected ].gid_ext =
1391+ ntohll (aclc -> d1 .gid_ext );
1392+ /* for non-virtual ISM devices, peer gid_ext remains 0. */
13781393 }
1379- ini -> ism_peer_gid [ini -> ism_selected ] = ntohll (aclc -> d0 .gid );
1394+ ini -> ism_peer_gid [ini -> ism_selected ]. gid = ntohll (aclc -> d0 .gid );
13801395
13811396 /* there is only one lgr role for SMC-D; use server lock */
13821397 mutex_lock (& smc_server_lgr_pending );
@@ -2061,7 +2076,8 @@ static bool smc_is_already_selected(struct smcd_dev *smcd,
20612076
20622077/* check for ISM devices matching proposed ISM devices */
20632078static void smc_check_ism_v2_match (struct smc_init_info * ini ,
2064- u16 proposed_chid , u64 proposed_gid ,
2079+ u16 proposed_chid ,
2080+ struct smcd_gid * proposed_gid ,
20652081 unsigned int * matches )
20662082{
20672083 struct smcd_dev * smcd ;
@@ -2073,7 +2089,11 @@ static void smc_check_ism_v2_match(struct smc_init_info *ini,
20732089 continue ;
20742090 if (smc_ism_get_chid (smcd ) == proposed_chid &&
20752091 !smc_ism_cantalk (proposed_gid , ISM_RESERVED_VLANID , smcd )) {
2076- ini -> ism_peer_gid [* matches ] = proposed_gid ;
2092+ ini -> ism_peer_gid [* matches ].gid = proposed_gid -> gid ;
2093+ if (__smc_ism_is_virtual (proposed_chid ))
2094+ ini -> ism_peer_gid [* matches ].gid_ext =
2095+ proposed_gid -> gid_ext ;
2096+ /* non-virtual ISM's peer gid_ext remains 0. */
20772097 ini -> ism_dev [* matches ] = smcd ;
20782098 (* matches )++ ;
20792099 break ;
@@ -2095,9 +2115,11 @@ static void smc_find_ism_v2_device_serv(struct smc_sock *new_smc,
20952115 struct smc_clc_v2_extension * smc_v2_ext ;
20962116 struct smc_clc_msg_smcd * pclc_smcd ;
20972117 unsigned int matches = 0 ;
2118+ struct smcd_gid smcd_gid ;
20982119 u8 smcd_version ;
20992120 u8 * eid = NULL ;
21002121 int i , rc ;
2122+ u16 chid ;
21012123
21022124 if (!(ini -> smcd_version & SMC_V2 ) || !smcd_indicated (ini -> smc_type_v2 ))
21032125 goto not_found ;
@@ -2107,18 +2129,35 @@ static void smc_find_ism_v2_device_serv(struct smc_sock *new_smc,
21072129 smcd_v2_ext = smc_get_clc_smcd_v2_ext (smc_v2_ext );
21082130
21092131 mutex_lock (& smcd_dev_list .mutex );
2110- if (pclc_smcd -> ism .chid )
2132+ if (pclc_smcd -> ism .chid ) {
21112133 /* check for ISM device matching proposed native ISM device */
2134+ smcd_gid .gid = ntohll (pclc_smcd -> ism .gid );
2135+ smcd_gid .gid_ext = 0 ;
21122136 smc_check_ism_v2_match (ini , ntohs (pclc_smcd -> ism .chid ),
2113- ntohll (pclc_smcd -> ism .gid ), & matches );
2114- for (i = 1 ; i <= smc_v2_ext -> hdr .ism_gid_cnt ; i ++ ) {
2137+ & smcd_gid , & matches );
2138+ }
2139+ for (i = 0 ; i < smc_v2_ext -> hdr .ism_gid_cnt ; i ++ ) {
21152140 /* check for ISM devices matching proposed non-native ISM
21162141 * devices
21172142 */
2118- smc_check_ism_v2_match (ini ,
2119- ntohs (smcd_v2_ext -> gidchid [i - 1 ].chid ),
2120- ntohll (smcd_v2_ext -> gidchid [i - 1 ].gid ),
2121- & matches );
2143+ smcd_gid .gid = ntohll (smcd_v2_ext -> gidchid [i ].gid );
2144+ smcd_gid .gid_ext = 0 ;
2145+ chid = ntohs (smcd_v2_ext -> gidchid [i ].chid );
2146+ if (__smc_ism_is_virtual (chid )) {
2147+ if ((i + 1 ) == smc_v2_ext -> hdr .ism_gid_cnt ||
2148+ chid != ntohs (smcd_v2_ext -> gidchid [i + 1 ].chid ))
2149+ /* each virtual ISM device takes two GID-CHID
2150+ * entries and CHID of the second entry repeats
2151+ * that of the first entry.
2152+ *
2153+ * So check if the next GID-CHID entry exists
2154+ * and both two entries' CHIDs are the same.
2155+ */
2156+ continue ;
2157+ smcd_gid .gid_ext =
2158+ ntohll (smcd_v2_ext -> gidchid [++ i ].gid );
2159+ }
2160+ smc_check_ism_v2_match (ini , chid , & smcd_gid , & matches );
21222161 }
21232162 mutex_unlock (& smcd_dev_list .mutex );
21242163
@@ -2167,7 +2206,8 @@ static void smc_find_ism_v1_device_serv(struct smc_sock *new_smc,
21672206 if (!(ini -> smcd_version & SMC_V1 ) || !smcd_indicated (ini -> smc_type_v1 ))
21682207 goto not_found ;
21692208 ini -> is_smcd = true; /* prepare ISM check */
2170- ini -> ism_peer_gid [0 ] = ntohll (pclc_smcd -> ism .gid );
2209+ ini -> ism_peer_gid [0 ].gid = ntohll (pclc_smcd -> ism .gid );
2210+ ini -> ism_peer_gid [0 ].gid_ext = 0 ;
21712211 rc = smc_find_ism_device (new_smc , ini );
21722212 if (rc )
21732213 goto not_found ;
0 commit comments