forked from mirrors/linux
		
	net/smc: compatible with 128-bits extended GID of virtual ISM device
According to virtual ISM support feature defined by SMCv2.1, GIDs of virtual ISM device are UUIDs defined by RFC4122, which are 128-bits long. So some adaptation work is required. And note that the GIDs of existing platform firmware ISM devices still remain 64-bits long. Signed-off-by: Wen Gu <guwen@linux.alibaba.com> Reviewed-by: Alexandra Winter <wintera@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									8dd512df3c
								
							
						
					
					
						commit
						b40584d145
					
				
					 12 changed files with 167 additions and 68 deletions
				
			
		| 
						 | 
					@ -743,10 +743,10 @@ static int ism_query_rgid(struct ism_dev *ism, u64 rgid, u32 vid_valid,
 | 
				
			||||||
	return ism_cmd(ism, &cmd);
 | 
						return ism_cmd(ism, &cmd);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int smcd_query_rgid(struct smcd_dev *smcd, u64 rgid, u32 vid_valid,
 | 
					static int smcd_query_rgid(struct smcd_dev *smcd, struct smcd_gid *rgid,
 | 
				
			||||||
			   u32 vid)
 | 
								   u32 vid_valid, u32 vid)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return ism_query_rgid(smcd->priv, rgid, vid_valid, vid);
 | 
						return ism_query_rgid(smcd->priv, rgid->gid, vid_valid, vid);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int smcd_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb,
 | 
					static int smcd_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb,
 | 
				
			||||||
| 
						 | 
					@ -797,10 +797,11 @@ static int ism_signal_ieq(struct ism_dev *ism, u64 rgid, u32 trigger_irq,
 | 
				
			||||||
	return ism_cmd(ism, &cmd);
 | 
						return ism_cmd(ism, &cmd);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int smcd_signal_ieq(struct smcd_dev *smcd, u64 rgid, u32 trigger_irq,
 | 
					static int smcd_signal_ieq(struct smcd_dev *smcd, struct smcd_gid *rgid,
 | 
				
			||||||
			   u32 event_code, u64 info)
 | 
								   u32 trigger_irq, u32 event_code, u64 info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return ism_signal_ieq(smcd->priv, rgid, trigger_irq, event_code, info);
 | 
						return ism_signal_ieq(smcd->priv, rgid->gid,
 | 
				
			||||||
 | 
								      trigger_irq, event_code, info);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int smcd_move(struct smcd_dev *smcd, u64 dmb_tok, unsigned int idx,
 | 
					static int smcd_move(struct smcd_dev *smcd, u64 dmb_tok, unsigned int idx,
 | 
				
			||||||
| 
						 | 
					@ -821,9 +822,11 @@ static u64 ism_get_local_gid(struct ism_dev *ism)
 | 
				
			||||||
	return ism->local_gid;
 | 
						return ism->local_gid;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static u64 smcd_get_local_gid(struct smcd_dev *smcd)
 | 
					static void smcd_get_local_gid(struct smcd_dev *smcd,
 | 
				
			||||||
 | 
								       struct smcd_gid *smcd_gid)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return ism_get_local_gid(smcd->priv);
 | 
						smcd_gid->gid = ism_get_local_gid(smcd->priv);
 | 
				
			||||||
 | 
						smcd_gid->gid_ext = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static u16 ism_get_chid(struct ism_dev *ism)
 | 
					static u16 ism_get_chid(struct ism_dev *ism)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,9 +52,14 @@ struct smcd_dmb {
 | 
				
			||||||
struct smcd_dev;
 | 
					struct smcd_dev;
 | 
				
			||||||
struct ism_client;
 | 
					struct ism_client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct smcd_gid {
 | 
				
			||||||
 | 
						u64	gid;
 | 
				
			||||||
 | 
						u64	gid_ext;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct smcd_ops {
 | 
					struct smcd_ops {
 | 
				
			||||||
	int (*query_remote_gid)(struct smcd_dev *dev, u64 rgid, u32 vid_valid,
 | 
						int (*query_remote_gid)(struct smcd_dev *dev, struct smcd_gid *rgid,
 | 
				
			||||||
				u32 vid);
 | 
									u32 vid_valid, u32 vid);
 | 
				
			||||||
	int (*register_dmb)(struct smcd_dev *dev, struct smcd_dmb *dmb,
 | 
						int (*register_dmb)(struct smcd_dev *dev, struct smcd_dmb *dmb,
 | 
				
			||||||
			    struct ism_client *client);
 | 
								    struct ism_client *client);
 | 
				
			||||||
	int (*unregister_dmb)(struct smcd_dev *dev, struct smcd_dmb *dmb);
 | 
						int (*unregister_dmb)(struct smcd_dev *dev, struct smcd_dmb *dmb);
 | 
				
			||||||
| 
						 | 
					@ -62,14 +67,14 @@ struct smcd_ops {
 | 
				
			||||||
	int (*del_vlan_id)(struct smcd_dev *dev, u64 vlan_id);
 | 
						int (*del_vlan_id)(struct smcd_dev *dev, u64 vlan_id);
 | 
				
			||||||
	int (*set_vlan_required)(struct smcd_dev *dev);
 | 
						int (*set_vlan_required)(struct smcd_dev *dev);
 | 
				
			||||||
	int (*reset_vlan_required)(struct smcd_dev *dev);
 | 
						int (*reset_vlan_required)(struct smcd_dev *dev);
 | 
				
			||||||
	int (*signal_event)(struct smcd_dev *dev, u64 rgid, u32 trigger_irq,
 | 
						int (*signal_event)(struct smcd_dev *dev, struct smcd_gid *rgid,
 | 
				
			||||||
			    u32 event_code, u64 info);
 | 
								    u32 trigger_irq, u32 event_code, u64 info);
 | 
				
			||||||
	int (*move_data)(struct smcd_dev *dev, u64 dmb_tok, unsigned int idx,
 | 
						int (*move_data)(struct smcd_dev *dev, u64 dmb_tok, unsigned int idx,
 | 
				
			||||||
			 bool sf, unsigned int offset, void *data,
 | 
								 bool sf, unsigned int offset, void *data,
 | 
				
			||||||
			 unsigned int size);
 | 
								 unsigned int size);
 | 
				
			||||||
	int (*supports_v2)(void);
 | 
						int (*supports_v2)(void);
 | 
				
			||||||
	u8* (*get_system_eid)(void);
 | 
						u8* (*get_system_eid)(void);
 | 
				
			||||||
	u64 (*get_local_gid)(struct smcd_dev *dev);
 | 
						void (*get_local_gid)(struct smcd_dev *dev, struct smcd_gid *gid);
 | 
				
			||||||
	u16 (*get_chid)(struct smcd_dev *dev);
 | 
						u16 (*get_chid)(struct smcd_dev *dev);
 | 
				
			||||||
	struct device* (*get_dev)(struct smcd_dev *dev);
 | 
						struct device* (*get_dev)(struct smcd_dev *dev);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1044,7 +1044,8 @@ static int smc_find_ism_v2_device_clnt(struct smc_sock *smc,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int rc = SMC_CLC_DECL_NOSMCDDEV;
 | 
						int rc = SMC_CLC_DECL_NOSMCDDEV;
 | 
				
			||||||
	struct smcd_dev *smcd;
 | 
						struct smcd_dev *smcd;
 | 
				
			||||||
	int i = 1;
 | 
						int i = 1, entry = 1;
 | 
				
			||||||
 | 
						bool is_virtual;
 | 
				
			||||||
	u16 chid;
 | 
						u16 chid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (smcd_indicated(ini->smc_type_v1))
 | 
						if (smcd_indicated(ini->smc_type_v1))
 | 
				
			||||||
| 
						 | 
					@ -1056,14 +1057,23 @@ static int smc_find_ism_v2_device_clnt(struct smc_sock *smc,
 | 
				
			||||||
		chid = smc_ism_get_chid(smcd);
 | 
							chid = smc_ism_get_chid(smcd);
 | 
				
			||||||
		if (!smc_find_ism_v2_is_unique_chid(chid, ini, i))
 | 
							if (!smc_find_ism_v2_is_unique_chid(chid, ini, i))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
							is_virtual = __smc_ism_is_virtual(chid);
 | 
				
			||||||
		if (!smc_pnet_is_pnetid_set(smcd->pnetid) ||
 | 
							if (!smc_pnet_is_pnetid_set(smcd->pnetid) ||
 | 
				
			||||||
		    smc_pnet_is_ndev_pnetid(sock_net(&smc->sk), smcd->pnetid)) {
 | 
							    smc_pnet_is_ndev_pnetid(sock_net(&smc->sk), smcd->pnetid)) {
 | 
				
			||||||
 | 
								if (is_virtual && entry == SMCD_CLC_MAX_V2_GID_ENTRIES)
 | 
				
			||||||
 | 
									/* It's the last GID-CHID entry left in CLC
 | 
				
			||||||
 | 
									 * Proposal SMC-Dv2 extension, but a virtual
 | 
				
			||||||
 | 
									 * ISM device will take two entries. So give
 | 
				
			||||||
 | 
									 * up it and try the next potential ISM device.
 | 
				
			||||||
 | 
									 */
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
			ini->ism_dev[i] = smcd;
 | 
								ini->ism_dev[i] = smcd;
 | 
				
			||||||
			ini->ism_chid[i] = chid;
 | 
								ini->ism_chid[i] = chid;
 | 
				
			||||||
			ini->is_smcd = true;
 | 
								ini->is_smcd = true;
 | 
				
			||||||
			rc = 0;
 | 
								rc = 0;
 | 
				
			||||||
			i++;
 | 
								i++;
 | 
				
			||||||
			if (i > SMC_MAX_ISM_DEVS)
 | 
								entry = is_virtual ? entry + 2 : entry + 1;
 | 
				
			||||||
 | 
								if (entry > SMCD_CLC_MAX_V2_GID_ENTRIES)
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1402,8 +1412,13 @@ static int smc_connect_ism(struct smc_sock *smc,
 | 
				
			||||||
		rc = smc_v2_determine_accepted_chid(aclc, ini);
 | 
							rc = smc_v2_determine_accepted_chid(aclc, ini);
 | 
				
			||||||
		if (rc)
 | 
							if (rc)
 | 
				
			||||||
			return rc;
 | 
								return rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (__smc_ism_is_virtual(ini->ism_chid[ini->ism_selected]))
 | 
				
			||||||
 | 
								ini->ism_peer_gid[ini->ism_selected].gid_ext =
 | 
				
			||||||
 | 
											ntohll(aclc->d1.gid_ext);
 | 
				
			||||||
 | 
							/* for non-virtual ISM devices, peer gid_ext remains 0. */
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ini->ism_peer_gid[ini->ism_selected] = ntohll(aclc->d0.gid);
 | 
						ini->ism_peer_gid[ini->ism_selected].gid = ntohll(aclc->d0.gid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* there is only one lgr role for SMC-D; use server lock */
 | 
						/* there is only one lgr role for SMC-D; use server lock */
 | 
				
			||||||
	mutex_lock(&smc_server_lgr_pending);
 | 
						mutex_lock(&smc_server_lgr_pending);
 | 
				
			||||||
| 
						 | 
					@ -2088,7 +2103,8 @@ static bool smc_is_already_selected(struct smcd_dev *smcd,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* check for ISM devices matching proposed ISM devices */
 | 
					/* check for ISM devices matching proposed ISM devices */
 | 
				
			||||||
static void smc_check_ism_v2_match(struct smc_init_info *ini,
 | 
					static void smc_check_ism_v2_match(struct smc_init_info *ini,
 | 
				
			||||||
				   u16 proposed_chid, u64 proposed_gid,
 | 
									   u16 proposed_chid,
 | 
				
			||||||
 | 
									   struct smcd_gid *proposed_gid,
 | 
				
			||||||
				   unsigned int *matches)
 | 
									   unsigned int *matches)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct smcd_dev *smcd;
 | 
						struct smcd_dev *smcd;
 | 
				
			||||||
| 
						 | 
					@ -2100,7 +2116,11 @@ static void smc_check_ism_v2_match(struct smc_init_info *ini,
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		if (smc_ism_get_chid(smcd) == proposed_chid &&
 | 
							if (smc_ism_get_chid(smcd) == proposed_chid &&
 | 
				
			||||||
		    !smc_ism_cantalk(proposed_gid, ISM_RESERVED_VLANID, smcd)) {
 | 
							    !smc_ism_cantalk(proposed_gid, ISM_RESERVED_VLANID, smcd)) {
 | 
				
			||||||
			ini->ism_peer_gid[*matches] = proposed_gid;
 | 
								ini->ism_peer_gid[*matches].gid = proposed_gid->gid;
 | 
				
			||||||
 | 
								if (__smc_ism_is_virtual(proposed_chid))
 | 
				
			||||||
 | 
									ini->ism_peer_gid[*matches].gid_ext =
 | 
				
			||||||
 | 
												proposed_gid->gid_ext;
 | 
				
			||||||
 | 
									/* non-virtual ISM's peer gid_ext remains 0. */
 | 
				
			||||||
			ini->ism_dev[*matches] = smcd;
 | 
								ini->ism_dev[*matches] = smcd;
 | 
				
			||||||
			(*matches)++;
 | 
								(*matches)++;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
| 
						 | 
					@ -2122,9 +2142,11 @@ static void smc_find_ism_v2_device_serv(struct smc_sock *new_smc,
 | 
				
			||||||
	struct smc_clc_v2_extension *smc_v2_ext;
 | 
						struct smc_clc_v2_extension *smc_v2_ext;
 | 
				
			||||||
	struct smc_clc_msg_smcd *pclc_smcd;
 | 
						struct smc_clc_msg_smcd *pclc_smcd;
 | 
				
			||||||
	unsigned int matches = 0;
 | 
						unsigned int matches = 0;
 | 
				
			||||||
 | 
						struct smcd_gid smcd_gid;
 | 
				
			||||||
	u8 smcd_version;
 | 
						u8 smcd_version;
 | 
				
			||||||
	u8 *eid = NULL;
 | 
						u8 *eid = NULL;
 | 
				
			||||||
	int i, rc;
 | 
						int i, rc;
 | 
				
			||||||
 | 
						u16 chid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!(ini->smcd_version & SMC_V2) || !smcd_indicated(ini->smc_type_v2))
 | 
						if (!(ini->smcd_version & SMC_V2) || !smcd_indicated(ini->smc_type_v2))
 | 
				
			||||||
		goto not_found;
 | 
							goto not_found;
 | 
				
			||||||
| 
						 | 
					@ -2134,18 +2156,35 @@ static void smc_find_ism_v2_device_serv(struct smc_sock *new_smc,
 | 
				
			||||||
	smcd_v2_ext = smc_get_clc_smcd_v2_ext(smc_v2_ext);
 | 
						smcd_v2_ext = smc_get_clc_smcd_v2_ext(smc_v2_ext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&smcd_dev_list.mutex);
 | 
						mutex_lock(&smcd_dev_list.mutex);
 | 
				
			||||||
	if (pclc_smcd->ism.chid)
 | 
						if (pclc_smcd->ism.chid) {
 | 
				
			||||||
		/* check for ISM device matching proposed native ISM device */
 | 
							/* check for ISM device matching proposed native ISM device */
 | 
				
			||||||
 | 
							smcd_gid.gid = ntohll(pclc_smcd->ism.gid);
 | 
				
			||||||
 | 
							smcd_gid.gid_ext = 0;
 | 
				
			||||||
		smc_check_ism_v2_match(ini, ntohs(pclc_smcd->ism.chid),
 | 
							smc_check_ism_v2_match(ini, ntohs(pclc_smcd->ism.chid),
 | 
				
			||||||
				       ntohll(pclc_smcd->ism.gid), &matches);
 | 
									       &smcd_gid, &matches);
 | 
				
			||||||
	for (i = 1; i <= smc_v2_ext->hdr.ism_gid_cnt; i++) {
 | 
						}
 | 
				
			||||||
 | 
						for (i = 0; i < smc_v2_ext->hdr.ism_gid_cnt; i++) {
 | 
				
			||||||
		/* check for ISM devices matching proposed non-native ISM
 | 
							/* check for ISM devices matching proposed non-native ISM
 | 
				
			||||||
		 * devices
 | 
							 * devices
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		smc_check_ism_v2_match(ini,
 | 
							smcd_gid.gid = ntohll(smcd_v2_ext->gidchid[i].gid);
 | 
				
			||||||
				       ntohs(smcd_v2_ext->gidchid[i - 1].chid),
 | 
							smcd_gid.gid_ext = 0;
 | 
				
			||||||
				       ntohll(smcd_v2_ext->gidchid[i - 1].gid),
 | 
							chid = ntohs(smcd_v2_ext->gidchid[i].chid);
 | 
				
			||||||
				       &matches);
 | 
							if (__smc_ism_is_virtual(chid)) {
 | 
				
			||||||
 | 
								if ((i + 1) == smc_v2_ext->hdr.ism_gid_cnt ||
 | 
				
			||||||
 | 
								    chid != ntohs(smcd_v2_ext->gidchid[i + 1].chid))
 | 
				
			||||||
 | 
									/* each virtual ISM device takes two GID-CHID
 | 
				
			||||||
 | 
									 * entries and CHID of the second entry repeats
 | 
				
			||||||
 | 
									 * that of the first entry.
 | 
				
			||||||
 | 
									 *
 | 
				
			||||||
 | 
									 * So check if the next GID-CHID entry exists
 | 
				
			||||||
 | 
									 * and both two entries' CHIDs are the same.
 | 
				
			||||||
 | 
									 */
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								smcd_gid.gid_ext =
 | 
				
			||||||
 | 
									ntohll(smcd_v2_ext->gidchid[++i].gid);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							smc_check_ism_v2_match(ini, chid, &smcd_gid, &matches);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	mutex_unlock(&smcd_dev_list.mutex);
 | 
						mutex_unlock(&smcd_dev_list.mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2194,7 +2233,8 @@ static void smc_find_ism_v1_device_serv(struct smc_sock *new_smc,
 | 
				
			||||||
	if (!(ini->smcd_version & SMC_V1) || !smcd_indicated(ini->smc_type_v1))
 | 
						if (!(ini->smcd_version & SMC_V1) || !smcd_indicated(ini->smc_type_v1))
 | 
				
			||||||
		goto not_found;
 | 
							goto not_found;
 | 
				
			||||||
	ini->is_smcd = true; /* prepare ISM check */
 | 
						ini->is_smcd = true; /* prepare ISM check */
 | 
				
			||||||
	ini->ism_peer_gid[0] = ntohll(pclc_smcd->ism.gid);
 | 
						ini->ism_peer_gid[0].gid = ntohll(pclc_smcd->ism.gid);
 | 
				
			||||||
 | 
						ini->ism_peer_gid[0].gid_ext = 0;
 | 
				
			||||||
	rc = smc_find_ism_device(new_smc, ini);
 | 
						rc = smc_find_ism_device(new_smc, ini);
 | 
				
			||||||
	if (rc)
 | 
						if (rc)
 | 
				
			||||||
		goto not_found;
 | 
							goto not_found;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,9 +29,6 @@
 | 
				
			||||||
#define SMCPROTO_SMC		0	/* SMC protocol, IPv4 */
 | 
					#define SMCPROTO_SMC		0	/* SMC protocol, IPv4 */
 | 
				
			||||||
#define SMCPROTO_SMC6		1	/* SMC protocol, IPv6 */
 | 
					#define SMCPROTO_SMC6		1	/* SMC protocol, IPv6 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SMC_MAX_ISM_DEVS	8	/* max # of proposed non-native ISM
 | 
					 | 
				
			||||||
					 * devices
 | 
					 | 
				
			||||||
					 */
 | 
					 | 
				
			||||||
#define SMC_AUTOCORKING_DEFAULT_SIZE	0x10000	/* 64K by default */
 | 
					#define SMC_AUTOCORKING_DEFAULT_SIZE	0x10000	/* 64K by default */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern struct proto smc_proto;
 | 
					extern struct proto smc_proto;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -883,11 +883,13 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
 | 
				
			||||||
		       ETH_ALEN);
 | 
							       ETH_ALEN);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (smcd_indicated(ini->smc_type_v1)) {
 | 
						if (smcd_indicated(ini->smc_type_v1)) {
 | 
				
			||||||
 | 
							struct smcd_gid smcd_gid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* add SMC-D specifics */
 | 
							/* add SMC-D specifics */
 | 
				
			||||||
		if (ini->ism_dev[0]) {
 | 
							if (ini->ism_dev[0]) {
 | 
				
			||||||
			smcd = ini->ism_dev[0];
 | 
								smcd = ini->ism_dev[0];
 | 
				
			||||||
			pclc_smcd->ism.gid =
 | 
								smcd->ops->get_local_gid(smcd, &smcd_gid);
 | 
				
			||||||
				htonll(smcd->ops->get_local_gid(smcd));
 | 
								pclc_smcd->ism.gid = htonll(smcd_gid.gid);
 | 
				
			||||||
			pclc_smcd->ism.chid =
 | 
								pclc_smcd->ism.chid =
 | 
				
			||||||
				htons(smc_ism_get_chid(ini->ism_dev[0]));
 | 
									htons(smc_ism_get_chid(ini->ism_dev[0]));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -920,10 +922,11 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
 | 
				
			||||||
		read_unlock(&smc_clc_eid_table.lock);
 | 
							read_unlock(&smc_clc_eid_table.lock);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (smcd_indicated(ini->smc_type_v2)) {
 | 
						if (smcd_indicated(ini->smc_type_v2)) {
 | 
				
			||||||
 | 
							struct smcd_gid smcd_gid;
 | 
				
			||||||
		u8 *eid = NULL;
 | 
							u8 *eid = NULL;
 | 
				
			||||||
 | 
							int entry = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		v2_ext->hdr.flag.seid = smc_clc_eid_table.seid_enabled;
 | 
							v2_ext->hdr.flag.seid = smc_clc_eid_table.seid_enabled;
 | 
				
			||||||
		v2_ext->hdr.ism_gid_cnt = ini->ism_offered_cnt;
 | 
					 | 
				
			||||||
		v2_ext->hdr.smcd_v2_ext_offset = htons(sizeof(*v2_ext) -
 | 
							v2_ext->hdr.smcd_v2_ext_offset = htons(sizeof(*v2_ext) -
 | 
				
			||||||
				offsetofend(struct smc_clnt_opts_area_hdr,
 | 
									offsetofend(struct smc_clnt_opts_area_hdr,
 | 
				
			||||||
					    smcd_v2_ext_offset) +
 | 
										    smcd_v2_ext_offset) +
 | 
				
			||||||
| 
						 | 
					@ -935,14 +938,26 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
 | 
				
			||||||
		if (ini->ism_offered_cnt) {
 | 
							if (ini->ism_offered_cnt) {
 | 
				
			||||||
			for (i = 1; i <= ini->ism_offered_cnt; i++) {
 | 
								for (i = 1; i <= ini->ism_offered_cnt; i++) {
 | 
				
			||||||
				smcd = ini->ism_dev[i];
 | 
									smcd = ini->ism_dev[i];
 | 
				
			||||||
				gidchids[i - 1].gid =
 | 
									smcd->ops->get_local_gid(smcd, &smcd_gid);
 | 
				
			||||||
					htonll(smcd->ops->get_local_gid(smcd));
 | 
									gidchids[entry].chid =
 | 
				
			||||||
				gidchids[i - 1].chid =
 | 
					 | 
				
			||||||
					htons(smc_ism_get_chid(ini->ism_dev[i]));
 | 
										htons(smc_ism_get_chid(ini->ism_dev[i]));
 | 
				
			||||||
 | 
									gidchids[entry].gid = htonll(smcd_gid.gid);
 | 
				
			||||||
 | 
									if (smc_ism_is_virtual(smcd)) {
 | 
				
			||||||
 | 
										/* a virtual ISM device takes two
 | 
				
			||||||
 | 
										 * entries. CHID of the second entry
 | 
				
			||||||
 | 
										 * repeats that of the first entry.
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
										gidchids[entry + 1].chid =
 | 
				
			||||||
 | 
											gidchids[entry].chid;
 | 
				
			||||||
 | 
										gidchids[entry + 1].gid =
 | 
				
			||||||
 | 
											htonll(smcd_gid.gid_ext);
 | 
				
			||||||
 | 
										entry++;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			plen += ini->ism_offered_cnt *
 | 
									entry++;
 | 
				
			||||||
				sizeof(struct smc_clc_smcd_gid_chid);
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								plen += entry * sizeof(struct smc_clc_smcd_gid_chid);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							v2_ext->hdr.ism_gid_cnt = entry;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (smcr_indicated(ini->smc_type_v2)) {
 | 
						if (smcr_indicated(ini->smc_type_v2)) {
 | 
				
			||||||
		memcpy(v2_ext->roce, ini->smcrv2.ib_gid_v2, SMC_GID_SIZE);
 | 
							memcpy(v2_ext->roce, ini->smcrv2.ib_gid_v2, SMC_GID_SIZE);
 | 
				
			||||||
| 
						 | 
					@ -978,7 +993,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
 | 
				
			||||||
			vec[i++].iov_len = sizeof(*smcd_v2_ext);
 | 
								vec[i++].iov_len = sizeof(*smcd_v2_ext);
 | 
				
			||||||
			if (ini->ism_offered_cnt) {
 | 
								if (ini->ism_offered_cnt) {
 | 
				
			||||||
				vec[i].iov_base = gidchids;
 | 
									vec[i].iov_base = gidchids;
 | 
				
			||||||
				vec[i++].iov_len = ini->ism_offered_cnt *
 | 
									vec[i++].iov_len = v2_ext->hdr.ism_gid_cnt *
 | 
				
			||||||
					sizeof(struct smc_clc_smcd_gid_chid);
 | 
										sizeof(struct smc_clc_smcd_gid_chid);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -1009,13 +1024,16 @@ smcd_clc_prep_confirm_accept(struct smc_connection *conn,
 | 
				
			||||||
			     struct smc_clc_msg_trail *trl)
 | 
								     struct smc_clc_msg_trail *trl)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct smcd_dev *smcd = conn->lgr->smcd;
 | 
						struct smcd_dev *smcd = conn->lgr->smcd;
 | 
				
			||||||
 | 
						struct smcd_gid smcd_gid;
 | 
				
			||||||
 | 
						u16 chid;
 | 
				
			||||||
	int len;
 | 
						int len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* SMC-D specific settings */
 | 
						/* SMC-D specific settings */
 | 
				
			||||||
	memcpy(clc->hdr.eyecatcher, SMCD_EYECATCHER,
 | 
						memcpy(clc->hdr.eyecatcher, SMCD_EYECATCHER,
 | 
				
			||||||
	       sizeof(SMCD_EYECATCHER));
 | 
						       sizeof(SMCD_EYECATCHER));
 | 
				
			||||||
 | 
						smcd->ops->get_local_gid(smcd, &smcd_gid);
 | 
				
			||||||
	clc->hdr.typev1 = SMC_TYPE_D;
 | 
						clc->hdr.typev1 = SMC_TYPE_D;
 | 
				
			||||||
	clc->d0.gid = htonll(smcd->ops->get_local_gid(smcd));
 | 
						clc->d0.gid = htonll(smcd_gid.gid);
 | 
				
			||||||
	clc->d0.token = htonll(conn->rmb_desc->token);
 | 
						clc->d0.token = htonll(conn->rmb_desc->token);
 | 
				
			||||||
	clc->d0.dmbe_size = conn->rmbe_size_comp;
 | 
						clc->d0.dmbe_size = conn->rmbe_size_comp;
 | 
				
			||||||
	clc->d0.dmbe_idx = 0;
 | 
						clc->d0.dmbe_idx = 0;
 | 
				
			||||||
| 
						 | 
					@ -1023,9 +1041,12 @@ smcd_clc_prep_confirm_accept(struct smc_connection *conn,
 | 
				
			||||||
	if (version == SMC_V1) {
 | 
						if (version == SMC_V1) {
 | 
				
			||||||
		clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN);
 | 
							clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		clc->d1.chid = htons(smc_ism_get_chid(smcd));
 | 
							chid = smc_ism_get_chid(smcd);
 | 
				
			||||||
 | 
							clc->d1.chid = htons(chid);
 | 
				
			||||||
		if (eid && eid[0])
 | 
							if (eid && eid[0])
 | 
				
			||||||
			memcpy(clc->d1.eid, eid, SMC_MAX_EID_LEN);
 | 
								memcpy(clc->d1.eid, eid, SMC_MAX_EID_LEN);
 | 
				
			||||||
 | 
							if (__smc_ism_is_virtual(chid))
 | 
				
			||||||
 | 
								clc->d1.gid_ext = htonll(smcd_gid.gid_ext);
 | 
				
			||||||
		len = SMCD_CLC_ACCEPT_CONFIRM_LEN_V2;
 | 
							len = SMCD_CLC_ACCEPT_CONFIRM_LEN_V2;
 | 
				
			||||||
		if (first_contact) {
 | 
							if (first_contact) {
 | 
				
			||||||
			*fce_len = smc_clc_fill_fce_v2x(fce_v2x, ini);
 | 
								*fce_len = smc_clc_fill_fce_v2x(fce_v2x, ini);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -172,6 +172,11 @@ struct smc_clc_msg_proposal {	/* clc proposal message sent by Linux */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SMC_CLC_MAX_V6_PREFIX		8
 | 
					#define SMC_CLC_MAX_V6_PREFIX		8
 | 
				
			||||||
#define SMC_CLC_MAX_UEID		8
 | 
					#define SMC_CLC_MAX_UEID		8
 | 
				
			||||||
 | 
					#define SMCD_CLC_MAX_V2_GID_ENTRIES	8 /* max # of CHID-GID entries in CLC
 | 
				
			||||||
 | 
										   * proposal SMC-Dv2 extension.
 | 
				
			||||||
 | 
										   * each ISM device takes one entry and
 | 
				
			||||||
 | 
										   * each virtual ISM takes two entries.
 | 
				
			||||||
 | 
										   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct smc_clc_msg_proposal_area {
 | 
					struct smc_clc_msg_proposal_area {
 | 
				
			||||||
	struct smc_clc_msg_proposal		pclc_base;
 | 
						struct smc_clc_msg_proposal		pclc_base;
 | 
				
			||||||
| 
						 | 
					@ -181,7 +186,8 @@ struct smc_clc_msg_proposal_area {
 | 
				
			||||||
	struct smc_clc_v2_extension		pclc_v2_ext;
 | 
						struct smc_clc_v2_extension		pclc_v2_ext;
 | 
				
			||||||
	u8			user_eids[SMC_CLC_MAX_UEID][SMC_MAX_EID_LEN];
 | 
						u8			user_eids[SMC_CLC_MAX_UEID][SMC_MAX_EID_LEN];
 | 
				
			||||||
	struct smc_clc_smcd_v2_extension	pclc_smcd_v2_ext;
 | 
						struct smc_clc_smcd_v2_extension	pclc_smcd_v2_ext;
 | 
				
			||||||
	struct smc_clc_smcd_gid_chid		pclc_gidchids[SMC_MAX_ISM_DEVS];
 | 
						struct smc_clc_smcd_gid_chid
 | 
				
			||||||
 | 
									pclc_gidchids[SMCD_CLC_MAX_V2_GID_ENTRIES];
 | 
				
			||||||
	struct smc_clc_msg_trail		pclc_trl;
 | 
						struct smc_clc_msg_trail		pclc_trl;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -277,7 +283,7 @@ struct smc_clc_msg_accept_confirm {	/* clc accept / confirm message */
 | 
				
			||||||
			struct { /* v2 only, but 12 bytes reserved in v1 */
 | 
								struct { /* v2 only, but 12 bytes reserved in v1 */
 | 
				
			||||||
				__be16 chid;
 | 
									__be16 chid;
 | 
				
			||||||
				u8 eid[SMC_MAX_EID_LEN];
 | 
									u8 eid[SMC_MAX_EID_LEN];
 | 
				
			||||||
				u8 reserved5[8];
 | 
									__be64 gid_ext;
 | 
				
			||||||
			} __packed d1;
 | 
								} __packed d1;
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -506,6 +506,7 @@ static int smc_nl_fill_smcd_lgr(struct smc_link_group *lgr,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char smc_pnet[SMC_MAX_PNETID_LEN + 1];
 | 
						char smc_pnet[SMC_MAX_PNETID_LEN + 1];
 | 
				
			||||||
	struct smcd_dev *smcd = lgr->smcd;
 | 
						struct smcd_dev *smcd = lgr->smcd;
 | 
				
			||||||
 | 
						struct smcd_gid smcd_gid;
 | 
				
			||||||
	struct nlattr *attrs;
 | 
						struct nlattr *attrs;
 | 
				
			||||||
	void *nlh;
 | 
						void *nlh;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -521,11 +522,11 @@ static int smc_nl_fill_smcd_lgr(struct smc_link_group *lgr,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (nla_put_u32(skb, SMC_NLA_LGR_D_ID, *((u32 *)&lgr->id)))
 | 
						if (nla_put_u32(skb, SMC_NLA_LGR_D_ID, *((u32 *)&lgr->id)))
 | 
				
			||||||
		goto errattr;
 | 
							goto errattr;
 | 
				
			||||||
 | 
						smcd->ops->get_local_gid(smcd, &smcd_gid);
 | 
				
			||||||
	if (nla_put_u64_64bit(skb, SMC_NLA_LGR_D_GID,
 | 
						if (nla_put_u64_64bit(skb, SMC_NLA_LGR_D_GID,
 | 
				
			||||||
			      smcd->ops->get_local_gid(smcd),
 | 
								      smcd_gid.gid, SMC_NLA_LGR_D_PAD))
 | 
				
			||||||
				  SMC_NLA_LGR_D_PAD))
 | 
					 | 
				
			||||||
		goto errattr;
 | 
							goto errattr;
 | 
				
			||||||
	if (nla_put_u64_64bit(skb, SMC_NLA_LGR_D_PEER_GID, lgr->peer_gid,
 | 
						if (nla_put_u64_64bit(skb, SMC_NLA_LGR_D_PEER_GID, lgr->peer_gid.gid,
 | 
				
			||||||
			      SMC_NLA_LGR_D_PAD))
 | 
								      SMC_NLA_LGR_D_PAD))
 | 
				
			||||||
		goto errattr;
 | 
							goto errattr;
 | 
				
			||||||
	if (nla_put_u8(skb, SMC_NLA_LGR_D_VLAN_ID, lgr->vlan_id))
 | 
						if (nla_put_u8(skb, SMC_NLA_LGR_D_VLAN_ID, lgr->vlan_id))
 | 
				
			||||||
| 
						 | 
					@ -876,7 +877,10 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
 | 
				
			||||||
		/* SMC-D specific settings */
 | 
							/* SMC-D specific settings */
 | 
				
			||||||
		smcd = ini->ism_dev[ini->ism_selected];
 | 
							smcd = ini->ism_dev[ini->ism_selected];
 | 
				
			||||||
		get_device(smcd->ops->get_dev(smcd));
 | 
							get_device(smcd->ops->get_dev(smcd));
 | 
				
			||||||
		lgr->peer_gid = ini->ism_peer_gid[ini->ism_selected];
 | 
							lgr->peer_gid.gid =
 | 
				
			||||||
 | 
								ini->ism_peer_gid[ini->ism_selected].gid;
 | 
				
			||||||
 | 
							lgr->peer_gid.gid_ext =
 | 
				
			||||||
 | 
								ini->ism_peer_gid[ini->ism_selected].gid_ext;
 | 
				
			||||||
		lgr->smcd = ini->ism_dev[ini->ism_selected];
 | 
							lgr->smcd = ini->ism_dev[ini->ism_selected];
 | 
				
			||||||
		lgr_list = &ini->ism_dev[ini->ism_selected]->lgr_list;
 | 
							lgr_list = &ini->ism_dev[ini->ism_selected]->lgr_list;
 | 
				
			||||||
		lgr_lock = &lgr->smcd->lgr_lock;
 | 
							lgr_lock = &lgr->smcd->lgr_lock;
 | 
				
			||||||
| 
						 | 
					@ -1514,7 +1518,8 @@ void smc_lgr_terminate_sched(struct smc_link_group *lgr)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Called when peer lgr shutdown (regularly or abnormally) is received */
 | 
					/* Called when peer lgr shutdown (regularly or abnormally) is received */
 | 
				
			||||||
void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan)
 | 
					void smc_smcd_terminate(struct smcd_dev *dev, struct smcd_gid *peer_gid,
 | 
				
			||||||
 | 
								unsigned short vlan)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct smc_link_group *lgr, *l;
 | 
						struct smc_link_group *lgr, *l;
 | 
				
			||||||
	LIST_HEAD(lgr_free_list);
 | 
						LIST_HEAD(lgr_free_list);
 | 
				
			||||||
| 
						 | 
					@ -1522,9 +1527,12 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan)
 | 
				
			||||||
	/* run common cleanup function and build free list */
 | 
						/* run common cleanup function and build free list */
 | 
				
			||||||
	spin_lock_bh(&dev->lgr_lock);
 | 
						spin_lock_bh(&dev->lgr_lock);
 | 
				
			||||||
	list_for_each_entry_safe(lgr, l, &dev->lgr_list, list) {
 | 
						list_for_each_entry_safe(lgr, l, &dev->lgr_list, list) {
 | 
				
			||||||
		if ((!peer_gid || lgr->peer_gid == peer_gid) &&
 | 
							if ((!peer_gid->gid ||
 | 
				
			||||||
 | 
							     (lgr->peer_gid.gid == peer_gid->gid &&
 | 
				
			||||||
 | 
							      !smc_ism_is_virtual(dev) ? 1 :
 | 
				
			||||||
 | 
							      lgr->peer_gid.gid_ext == peer_gid->gid_ext)) &&
 | 
				
			||||||
		    (vlan == VLAN_VID_MASK || lgr->vlan_id == vlan)) {
 | 
							    (vlan == VLAN_VID_MASK || lgr->vlan_id == vlan)) {
 | 
				
			||||||
			if (peer_gid) /* peer triggered termination */
 | 
								if (peer_gid->gid) /* peer triggered termination */
 | 
				
			||||||
				lgr->peer_shutdown = 1;
 | 
									lgr->peer_shutdown = 1;
 | 
				
			||||||
			list_move(&lgr->list, &lgr_free_list);
 | 
								list_move(&lgr->list, &lgr_free_list);
 | 
				
			||||||
			lgr->freeing = 1;
 | 
								lgr->freeing = 1;
 | 
				
			||||||
| 
						 | 
					@ -1860,9 +1868,12 @@ static bool smcr_lgr_match(struct smc_link_group *lgr, u8 smcr_version,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool smcd_lgr_match(struct smc_link_group *lgr,
 | 
					static bool smcd_lgr_match(struct smc_link_group *lgr,
 | 
				
			||||||
			   struct smcd_dev *smcismdev, u64 peer_gid)
 | 
								   struct smcd_dev *smcismdev,
 | 
				
			||||||
 | 
								   struct smcd_gid *peer_gid)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return lgr->peer_gid == peer_gid && lgr->smcd == smcismdev;
 | 
						return lgr->peer_gid.gid == peer_gid->gid && lgr->smcd == smcismdev &&
 | 
				
			||||||
 | 
							smc_ism_is_virtual(smcismdev) ?
 | 
				
			||||||
 | 
							(lgr->peer_gid.gid_ext == peer_gid->gid_ext) : 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* create a new SMC connection (and a new link group if necessary) */
 | 
					/* create a new SMC connection (and a new link group if necessary) */
 | 
				
			||||||
| 
						 | 
					@ -1892,7 +1903,7 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
 | 
				
			||||||
		write_lock_bh(&lgr->conns_lock);
 | 
							write_lock_bh(&lgr->conns_lock);
 | 
				
			||||||
		if ((ini->is_smcd ?
 | 
							if ((ini->is_smcd ?
 | 
				
			||||||
		     smcd_lgr_match(lgr, ini->ism_dev[ini->ism_selected],
 | 
							     smcd_lgr_match(lgr, ini->ism_dev[ini->ism_selected],
 | 
				
			||||||
				    ini->ism_peer_gid[ini->ism_selected]) :
 | 
									    &ini->ism_peer_gid[ini->ism_selected]) :
 | 
				
			||||||
		     smcr_lgr_match(lgr, ini->smcr_version,
 | 
							     smcr_lgr_match(lgr, ini->smcr_version,
 | 
				
			||||||
				    ini->peer_systemid,
 | 
									    ini->peer_systemid,
 | 
				
			||||||
				    ini->peer_gid, ini->peer_mac, role,
 | 
									    ini->peer_gid, ini->peer_mac, role,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,9 +17,11 @@
 | 
				
			||||||
#include <linux/pci.h>
 | 
					#include <linux/pci.h>
 | 
				
			||||||
#include <rdma/ib_verbs.h>
 | 
					#include <rdma/ib_verbs.h>
 | 
				
			||||||
#include <net/genetlink.h>
 | 
					#include <net/genetlink.h>
 | 
				
			||||||
 | 
					#include <net/smc.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "smc.h"
 | 
					#include "smc.h"
 | 
				
			||||||
#include "smc_ib.h"
 | 
					#include "smc_ib.h"
 | 
				
			||||||
 | 
					#include "smc_clc.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SMC_RMBS_PER_LGR_MAX	255	/* max. # of RMBs per link group */
 | 
					#define SMC_RMBS_PER_LGR_MAX	255	/* max. # of RMBs per link group */
 | 
				
			||||||
#define SMC_CONN_PER_LGR_MIN	16	/* min. # of connections per link group */
 | 
					#define SMC_CONN_PER_LGR_MIN	16	/* min. # of connections per link group */
 | 
				
			||||||
| 
						 | 
					@ -355,7 +357,7 @@ struct smc_link_group {
 | 
				
			||||||
						/* max links can be added in lgr */
 | 
											/* max links can be added in lgr */
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		struct { /* SMC-D */
 | 
							struct { /* SMC-D */
 | 
				
			||||||
			u64			peer_gid;
 | 
								struct smcd_gid		peer_gid;
 | 
				
			||||||
						/* Peer GID (remote) */
 | 
											/* Peer GID (remote) */
 | 
				
			||||||
			struct smcd_dev		*smcd;
 | 
								struct smcd_dev		*smcd;
 | 
				
			||||||
						/* ISM device for VLAN reg. */
 | 
											/* ISM device for VLAN reg. */
 | 
				
			||||||
| 
						 | 
					@ -392,6 +394,11 @@ struct smc_init_info_smcrv2 {
 | 
				
			||||||
	struct smc_gidlist	gidlist;
 | 
						struct smc_gidlist	gidlist;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SMC_MAX_V2_ISM_DEVS	SMCD_CLC_MAX_V2_GID_ENTRIES
 | 
				
			||||||
 | 
									/* max # of proposed non-native ISM devices,
 | 
				
			||||||
 | 
									 * which can't exceed the max # of CHID-GID
 | 
				
			||||||
 | 
									 * entries in CLC proposal SMC-Dv2 extension.
 | 
				
			||||||
 | 
									 */
 | 
				
			||||||
struct smc_init_info {
 | 
					struct smc_init_info {
 | 
				
			||||||
	u8			is_smcd;
 | 
						u8			is_smcd;
 | 
				
			||||||
	u8			smc_type_v1;
 | 
						u8			smc_type_v1;
 | 
				
			||||||
| 
						 | 
					@ -417,9 +424,9 @@ struct smc_init_info {
 | 
				
			||||||
	u32			ib_clcqpn;
 | 
						u32			ib_clcqpn;
 | 
				
			||||||
	struct smc_init_info_smcrv2 smcrv2;
 | 
						struct smc_init_info_smcrv2 smcrv2;
 | 
				
			||||||
	/* SMC-D */
 | 
						/* SMC-D */
 | 
				
			||||||
	u64			ism_peer_gid[SMC_MAX_ISM_DEVS + 1];
 | 
						struct smcd_gid		ism_peer_gid[SMC_MAX_V2_ISM_DEVS + 1];
 | 
				
			||||||
	struct smcd_dev		*ism_dev[SMC_MAX_ISM_DEVS + 1];
 | 
						struct smcd_dev		*ism_dev[SMC_MAX_V2_ISM_DEVS + 1];
 | 
				
			||||||
	u16			ism_chid[SMC_MAX_ISM_DEVS + 1];
 | 
						u16			ism_chid[SMC_MAX_V2_ISM_DEVS + 1];
 | 
				
			||||||
	u8			ism_offered_cnt; /* # of ISM devices offered */
 | 
						u8			ism_offered_cnt; /* # of ISM devices offered */
 | 
				
			||||||
	u8			ism_selected;    /* index of selected ISM dev*/
 | 
						u8			ism_selected;    /* index of selected ISM dev*/
 | 
				
			||||||
	u8			smcd_version;
 | 
						u8			smcd_version;
 | 
				
			||||||
| 
						 | 
					@ -545,7 +552,7 @@ void smc_lgr_hold(struct smc_link_group *lgr);
 | 
				
			||||||
void smc_lgr_put(struct smc_link_group *lgr);
 | 
					void smc_lgr_put(struct smc_link_group *lgr);
 | 
				
			||||||
void smcr_port_add(struct smc_ib_device *smcibdev, u8 ibport);
 | 
					void smcr_port_add(struct smc_ib_device *smcibdev, u8 ibport);
 | 
				
			||||||
void smcr_port_err(struct smc_ib_device *smcibdev, u8 ibport);
 | 
					void smcr_port_err(struct smc_ib_device *smcibdev, u8 ibport);
 | 
				
			||||||
void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid,
 | 
					void smc_smcd_terminate(struct smcd_dev *dev, struct smcd_gid *peer_gid,
 | 
				
			||||||
			unsigned short vlan);
 | 
								unsigned short vlan);
 | 
				
			||||||
void smc_smcd_terminate_all(struct smcd_dev *dev);
 | 
					void smc_smcd_terminate_all(struct smcd_dev *dev);
 | 
				
			||||||
void smc_smcr_terminate_all(struct smc_ib_device *smcibdev);
 | 
					void smc_smcr_terminate_all(struct smc_ib_device *smcibdev);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "smc.h"
 | 
					#include "smc.h"
 | 
				
			||||||
#include "smc_core.h"
 | 
					#include "smc_core.h"
 | 
				
			||||||
 | 
					#include "smc_ism.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct smc_diag_dump_ctx {
 | 
					struct smc_diag_dump_ctx {
 | 
				
			||||||
	int pos[2];
 | 
						int pos[2];
 | 
				
			||||||
| 
						 | 
					@ -168,12 +169,14 @@ static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
		struct smc_connection *conn = &smc->conn;
 | 
							struct smc_connection *conn = &smc->conn;
 | 
				
			||||||
		struct smcd_diag_dmbinfo dinfo;
 | 
							struct smcd_diag_dmbinfo dinfo;
 | 
				
			||||||
		struct smcd_dev *smcd = conn->lgr->smcd;
 | 
							struct smcd_dev *smcd = conn->lgr->smcd;
 | 
				
			||||||
 | 
							struct smcd_gid smcd_gid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		memset(&dinfo, 0, sizeof(dinfo));
 | 
							memset(&dinfo, 0, sizeof(dinfo));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dinfo.linkid = *((u32 *)conn->lgr->id);
 | 
							dinfo.linkid = *((u32 *)conn->lgr->id);
 | 
				
			||||||
		dinfo.peer_gid = conn->lgr->peer_gid;
 | 
							dinfo.peer_gid = conn->lgr->peer_gid.gid;
 | 
				
			||||||
		dinfo.my_gid = smcd->ops->get_local_gid(smcd);
 | 
							smcd->ops->get_local_gid(smcd, &smcd_gid);
 | 
				
			||||||
 | 
							dinfo.my_gid = smcd_gid.gid;
 | 
				
			||||||
		dinfo.token = conn->rmb_desc->token;
 | 
							dinfo.token = conn->rmb_desc->token;
 | 
				
			||||||
		dinfo.peer_token = conn->peer_token;
 | 
							dinfo.peer_token = conn->peer_token;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,8 @@ static struct ism_client smc_ism_client = {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Test if an ISM communication is possible - same CPC */
 | 
					/* Test if an ISM communication is possible - same CPC */
 | 
				
			||||||
int smc_ism_cantalk(u64 peer_gid, unsigned short vlan_id, struct smcd_dev *smcd)
 | 
					int smc_ism_cantalk(struct smcd_gid *peer_gid, unsigned short vlan_id,
 | 
				
			||||||
 | 
							    struct smcd_dev *smcd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return smcd->ops->query_remote_gid(smcd, peer_gid, vlan_id ? 1 : 0,
 | 
						return smcd->ops->query_remote_gid(smcd, peer_gid, vlan_id ? 1 : 0,
 | 
				
			||||||
					   vlan_id);
 | 
										   vlan_id);
 | 
				
			||||||
| 
						 | 
					@ -208,7 +209,7 @@ int smc_ism_register_dmb(struct smc_link_group *lgr, int dmb_len,
 | 
				
			||||||
	dmb.dmb_len = dmb_len;
 | 
						dmb.dmb_len = dmb_len;
 | 
				
			||||||
	dmb.sba_idx = dmb_desc->sba_idx;
 | 
						dmb.sba_idx = dmb_desc->sba_idx;
 | 
				
			||||||
	dmb.vlan_id = lgr->vlan_id;
 | 
						dmb.vlan_id = lgr->vlan_id;
 | 
				
			||||||
	dmb.rgid = lgr->peer_gid;
 | 
						dmb.rgid = lgr->peer_gid.gid;
 | 
				
			||||||
	rc = lgr->smcd->ops->register_dmb(lgr->smcd, &dmb, &smc_ism_client);
 | 
						rc = lgr->smcd->ops->register_dmb(lgr->smcd, &dmb, &smc_ism_client);
 | 
				
			||||||
	if (!rc) {
 | 
						if (!rc) {
 | 
				
			||||||
		dmb_desc->sba_idx = dmb.sba_idx;
 | 
							dmb_desc->sba_idx = dmb.sba_idx;
 | 
				
			||||||
| 
						 | 
					@ -340,18 +341,20 @@ union smcd_sw_event_info {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void smcd_handle_sw_event(struct smc_ism_event_work *wrk)
 | 
					static void smcd_handle_sw_event(struct smc_ism_event_work *wrk)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct smcd_gid peer_gid = { .gid = wrk->event.tok,
 | 
				
			||||||
 | 
									     .gid_ext = 0 };
 | 
				
			||||||
	union smcd_sw_event_info ev_info;
 | 
						union smcd_sw_event_info ev_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ev_info.info = wrk->event.info;
 | 
						ev_info.info = wrk->event.info;
 | 
				
			||||||
	switch (wrk->event.code) {
 | 
						switch (wrk->event.code) {
 | 
				
			||||||
	case ISM_EVENT_CODE_SHUTDOWN:	/* Peer shut down DMBs */
 | 
						case ISM_EVENT_CODE_SHUTDOWN:	/* Peer shut down DMBs */
 | 
				
			||||||
		smc_smcd_terminate(wrk->smcd, wrk->event.tok, ev_info.vlan_id);
 | 
							smc_smcd_terminate(wrk->smcd, &peer_gid, ev_info.vlan_id);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case ISM_EVENT_CODE_TESTLINK:	/* Activity timer */
 | 
						case ISM_EVENT_CODE_TESTLINK:	/* Activity timer */
 | 
				
			||||||
		if (ev_info.code == ISM_EVENT_REQUEST) {
 | 
							if (ev_info.code == ISM_EVENT_REQUEST) {
 | 
				
			||||||
			ev_info.code = ISM_EVENT_RESPONSE;
 | 
								ev_info.code = ISM_EVENT_RESPONSE;
 | 
				
			||||||
			wrk->smcd->ops->signal_event(wrk->smcd,
 | 
								wrk->smcd->ops->signal_event(wrk->smcd,
 | 
				
			||||||
						     wrk->event.tok,
 | 
											     &peer_gid,
 | 
				
			||||||
						     ISM_EVENT_REQUEST_IR,
 | 
											     ISM_EVENT_REQUEST_IR,
 | 
				
			||||||
						     ISM_EVENT_CODE_TESTLINK,
 | 
											     ISM_EVENT_CODE_TESTLINK,
 | 
				
			||||||
						     ev_info.info);
 | 
											     ev_info.info);
 | 
				
			||||||
| 
						 | 
					@ -365,10 +368,12 @@ static void smc_ism_event_work(struct work_struct *work)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct smc_ism_event_work *wrk =
 | 
						struct smc_ism_event_work *wrk =
 | 
				
			||||||
		container_of(work, struct smc_ism_event_work, work);
 | 
							container_of(work, struct smc_ism_event_work, work);
 | 
				
			||||||
 | 
						struct smcd_gid smcd_gid = { .gid = wrk->event.tok,
 | 
				
			||||||
 | 
									     .gid_ext = 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (wrk->event.type) {
 | 
						switch (wrk->event.type) {
 | 
				
			||||||
	case ISM_EVENT_GID:	/* GID event, token is peer GID */
 | 
						case ISM_EVENT_GID:	/* GID event, token is peer GID */
 | 
				
			||||||
		smc_smcd_terminate(wrk->smcd, wrk->event.tok, VLAN_VID_MASK);
 | 
							smc_smcd_terminate(wrk->smcd, &smcd_gid, VLAN_VID_MASK);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case ISM_EVENT_DMB:
 | 
						case ISM_EVENT_DMB:
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
| 
						 | 
					@ -525,7 +530,7 @@ int smc_ism_signal_shutdown(struct smc_link_group *lgr)
 | 
				
			||||||
	memcpy(ev_info.uid, lgr->id, SMC_LGR_ID_SIZE);
 | 
						memcpy(ev_info.uid, lgr->id, SMC_LGR_ID_SIZE);
 | 
				
			||||||
	ev_info.vlan_id = lgr->vlan_id;
 | 
						ev_info.vlan_id = lgr->vlan_id;
 | 
				
			||||||
	ev_info.code = ISM_EVENT_REQUEST;
 | 
						ev_info.code = ISM_EVENT_REQUEST;
 | 
				
			||||||
	rc = lgr->smcd->ops->signal_event(lgr->smcd, lgr->peer_gid,
 | 
						rc = lgr->smcd->ops->signal_event(lgr->smcd, &lgr->peer_gid,
 | 
				
			||||||
					  ISM_EVENT_REQUEST_IR,
 | 
										  ISM_EVENT_REQUEST_IR,
 | 
				
			||||||
					  ISM_EVENT_CODE_SHUTDOWN,
 | 
										  ISM_EVENT_CODE_SHUTDOWN,
 | 
				
			||||||
					  ev_info.info);
 | 
										  ev_info.info);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,8 @@ struct smc_ism_vlanid {			/* VLAN id set on ISM device */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct smcd_dev;
 | 
					struct smcd_dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int smc_ism_cantalk(u64 peer_gid, unsigned short vlan_id, struct smcd_dev *dev);
 | 
					int smc_ism_cantalk(struct smcd_gid *peer_gid, unsigned short vlan_id,
 | 
				
			||||||
 | 
							    struct smcd_dev *dev);
 | 
				
			||||||
void smc_ism_set_conn(struct smc_connection *conn);
 | 
					void smc_ism_set_conn(struct smc_connection *conn);
 | 
				
			||||||
void smc_ism_unset_conn(struct smc_connection *conn);
 | 
					void smc_ism_unset_conn(struct smc_connection *conn);
 | 
				
			||||||
int smc_ism_get_vlan(struct smcd_dev *dev, unsigned short vlan_id);
 | 
					int smc_ism_get_vlan(struct smcd_dev *dev, unsigned short vlan_id);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1103,8 +1103,8 @@ static void smc_pnet_find_ism_by_pnetid(struct net_device *ndev,
 | 
				
			||||||
	list_for_each_entry(ismdev, &smcd_dev_list.list, list) {
 | 
						list_for_each_entry(ismdev, &smcd_dev_list.list, list) {
 | 
				
			||||||
		if (smc_pnet_match(ismdev->pnetid, ndev_pnetid) &&
 | 
							if (smc_pnet_match(ismdev->pnetid, ndev_pnetid) &&
 | 
				
			||||||
		    !ismdev->going_away &&
 | 
							    !ismdev->going_away &&
 | 
				
			||||||
		    (!ini->ism_peer_gid[0] ||
 | 
							    (!ini->ism_peer_gid[0].gid ||
 | 
				
			||||||
		     !smc_ism_cantalk(ini->ism_peer_gid[0], ini->vlan_id,
 | 
							     !smc_ism_cantalk(&ini->ism_peer_gid[0], ini->vlan_id,
 | 
				
			||||||
				      ismdev))) {
 | 
									      ismdev))) {
 | 
				
			||||||
			ini->ism_dev[0] = ismdev;
 | 
								ini->ism_dev[0] = ismdev;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue