@@ -1044,7 +1044,8 @@ static int smc_find_ism_v2_device_clnt(struct smc_sock *smc,
10441044{
10451045 int rc = SMC_CLC_DECL_NOSMCDDEV ;
10461046 struct smcd_dev * smcd ;
1047- int i = 1 ;
1047+ int i = 1 , entry = 1 ;
1048+ bool is_virtual ;
10481049 u16 chid ;
10491050
10501051 if (smcd_indicated (ini -> smc_type_v1 ))
@@ -1056,14 +1057,23 @@ static int smc_find_ism_v2_device_clnt(struct smc_sock *smc,
10561057 chid = smc_ism_get_chid (smcd );
10571058 if (!smc_find_ism_v2_is_unique_chid (chid , ini , i ))
10581059 continue ;
1060+ is_virtual = __smc_ism_is_virtual (chid );
10591061 if (!smc_pnet_is_pnetid_set (smcd -> pnetid ) ||
10601062 smc_pnet_is_ndev_pnetid (sock_net (& smc -> sk ), smcd -> pnetid )) {
1063+ if (is_virtual && entry == SMCD_CLC_MAX_V2_GID_ENTRIES )
1064+ /* It's the last GID-CHID entry left in CLC
1065+ * Proposal SMC-Dv2 extension, but a virtual
1066+ * ISM device will take two entries. So give
1067+ * up it and try the next potential ISM device.
1068+ */
1069+ continue ;
10611070 ini -> ism_dev [i ] = smcd ;
10621071 ini -> ism_chid [i ] = chid ;
10631072 ini -> is_smcd = true;
10641073 rc = 0 ;
10651074 i ++ ;
1066- if (i > SMC_MAX_ISM_DEVS )
1075+ entry = is_virtual ? entry + 2 : entry + 1 ;
1076+ if (entry > SMCD_CLC_MAX_V2_GID_ENTRIES )
10671077 break ;
10681078 }
10691079 }
@@ -1402,8 +1412,13 @@ static int smc_connect_ism(struct smc_sock *smc,
14021412 rc = smc_v2_determine_accepted_chid (aclc , ini );
14031413 if (rc )
14041414 return rc ;
1415+
1416+ if (__smc_ism_is_virtual (ini -> ism_chid [ini -> ism_selected ]))
1417+ ini -> ism_peer_gid [ini -> ism_selected ].gid_ext =
1418+ ntohll (aclc -> d1 .gid_ext );
1419+ /* for non-virtual ISM devices, peer gid_ext remains 0. */
14051420 }
1406- ini -> ism_peer_gid [ini -> ism_selected ] = ntohll (aclc -> d0 .gid );
1421+ ini -> ism_peer_gid [ini -> ism_selected ]. gid = ntohll (aclc -> d0 .gid );
14071422
14081423 /* there is only one lgr role for SMC-D; use server lock */
14091424 mutex_lock (& smc_server_lgr_pending );
@@ -2088,7 +2103,8 @@ static bool smc_is_already_selected(struct smcd_dev *smcd,
20882103
20892104/* check for ISM devices matching proposed ISM devices */
20902105static void smc_check_ism_v2_match (struct smc_init_info * ini ,
2091- u16 proposed_chid , u64 proposed_gid ,
2106+ u16 proposed_chid ,
2107+ struct smcd_gid * proposed_gid ,
20922108 unsigned int * matches )
20932109{
20942110 struct smcd_dev * smcd ;
@@ -2100,7 +2116,11 @@ static void smc_check_ism_v2_match(struct smc_init_info *ini,
21002116 continue ;
21012117 if (smc_ism_get_chid (smcd ) == proposed_chid &&
21022118 !smc_ism_cantalk (proposed_gid , ISM_RESERVED_VLANID , smcd )) {
2103- ini -> ism_peer_gid [* matches ] = proposed_gid ;
2119+ ini -> ism_peer_gid [* matches ].gid = proposed_gid -> gid ;
2120+ if (__smc_ism_is_virtual (proposed_chid ))
2121+ ini -> ism_peer_gid [* matches ].gid_ext =
2122+ proposed_gid -> gid_ext ;
2123+ /* non-virtual ISM's peer gid_ext remains 0. */
21042124 ini -> ism_dev [* matches ] = smcd ;
21052125 (* matches )++ ;
21062126 break ;
@@ -2122,9 +2142,11 @@ static void smc_find_ism_v2_device_serv(struct smc_sock *new_smc,
21222142 struct smc_clc_v2_extension * smc_v2_ext ;
21232143 struct smc_clc_msg_smcd * pclc_smcd ;
21242144 unsigned int matches = 0 ;
2145+ struct smcd_gid smcd_gid ;
21252146 u8 smcd_version ;
21262147 u8 * eid = NULL ;
21272148 int i , rc ;
2149+ u16 chid ;
21282150
21292151 if (!(ini -> smcd_version & SMC_V2 ) || !smcd_indicated (ini -> smc_type_v2 ))
21302152 goto not_found ;
@@ -2134,18 +2156,35 @@ static void smc_find_ism_v2_device_serv(struct smc_sock *new_smc,
21342156 smcd_v2_ext = smc_get_clc_smcd_v2_ext (smc_v2_ext );
21352157
21362158 mutex_lock (& smcd_dev_list .mutex );
2137- if (pclc_smcd -> ism .chid )
2159+ if (pclc_smcd -> ism .chid ) {
21382160 /* check for ISM device matching proposed native ISM device */
2161+ smcd_gid .gid = ntohll (pclc_smcd -> ism .gid );
2162+ smcd_gid .gid_ext = 0 ;
21392163 smc_check_ism_v2_match (ini , ntohs (pclc_smcd -> ism .chid ),
2140- ntohll (pclc_smcd -> ism .gid ), & matches );
2141- for (i = 1 ; i <= smc_v2_ext -> hdr .ism_gid_cnt ; i ++ ) {
2164+ & smcd_gid , & matches );
2165+ }
2166+ for (i = 0 ; i < smc_v2_ext -> hdr .ism_gid_cnt ; i ++ ) {
21422167 /* check for ISM devices matching proposed non-native ISM
21432168 * devices
21442169 */
2145- smc_check_ism_v2_match (ini ,
2146- ntohs (smcd_v2_ext -> gidchid [i - 1 ].chid ),
2147- ntohll (smcd_v2_ext -> gidchid [i - 1 ].gid ),
2148- & matches );
2170+ smcd_gid .gid = ntohll (smcd_v2_ext -> gidchid [i ].gid );
2171+ smcd_gid .gid_ext = 0 ;
2172+ chid = ntohs (smcd_v2_ext -> gidchid [i ].chid );
2173+ if (__smc_ism_is_virtual (chid )) {
2174+ if ((i + 1 ) == smc_v2_ext -> hdr .ism_gid_cnt ||
2175+ chid != ntohs (smcd_v2_ext -> gidchid [i + 1 ].chid ))
2176+ /* each virtual ISM device takes two GID-CHID
2177+ * entries and CHID of the second entry repeats
2178+ * that of the first entry.
2179+ *
2180+ * So check if the next GID-CHID entry exists
2181+ * and both two entries' CHIDs are the same.
2182+ */
2183+ continue ;
2184+ smcd_gid .gid_ext =
2185+ ntohll (smcd_v2_ext -> gidchid [++ i ].gid );
2186+ }
2187+ smc_check_ism_v2_match (ini , chid , & smcd_gid , & matches );
21492188 }
21502189 mutex_unlock (& smcd_dev_list .mutex );
21512190
@@ -2194,7 +2233,8 @@ static void smc_find_ism_v1_device_serv(struct smc_sock *new_smc,
21942233 if (!(ini -> smcd_version & SMC_V1 ) || !smcd_indicated (ini -> smc_type_v1 ))
21952234 goto not_found ;
21962235 ini -> is_smcd = true; /* prepare ISM check */
2197- ini -> ism_peer_gid [0 ] = ntohll (pclc_smcd -> ism .gid );
2236+ ini -> ism_peer_gid [0 ].gid = ntohll (pclc_smcd -> ism .gid );
2237+ ini -> ism_peer_gid [0 ].gid_ext = 0 ;
21982238 rc = smc_find_ism_device (new_smc , ini );
21992239 if (rc )
22002240 goto not_found ;
0 commit comments