Commit 9a4c1d5d authored by Wen Gu's avatar Wen Gu Committed by Zhengchao Shao
Browse files

net/smc: compatible with 128-bits extended GID of virtual ISM device

mainline inclusion
from mainline-v6.8-rc1
commit b40584d145700addc70cc29e4f0850a4ed955b1c
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IACM52

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b40584d145700addc70cc29e4f0850a4ed955b1c



--------------------------------

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: default avatarWen Gu <guwen@linux.alibaba.com>
Reviewed-by: default avatarAlexandra Winter <wintera@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarZhengchao Shao <shaozhengchao@huawei.com>
parent f710e92e
Loading
Loading
Loading
Loading
+11 −8
Original line number Diff line number Diff line
@@ -762,10 +762,10 @@ static int ism_query_rgid(struct ism_dev *ism, u64 rgid, u32 vid_valid,
	return ism_cmd(ism, &cmd);
}

static int smcd_query_rgid(struct smcd_dev *smcd, u64 rgid, u32 vid_valid,
			   u32 vid)
static int smcd_query_rgid(struct smcd_dev *smcd, struct smcd_gid *rgid,
			   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,
@@ -816,10 +816,11 @@ static int ism_signal_ieq(struct ism_dev *ism, u64 rgid, u32 trigger_irq,
	return ism_cmd(ism, &cmd);
}

static int smcd_signal_ieq(struct smcd_dev *smcd, u64 rgid, u32 trigger_irq,
			   u32 event_code, u64 info)
static int smcd_signal_ieq(struct smcd_dev *smcd, struct smcd_gid *rgid,
			   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,
@@ -840,9 +841,11 @@ static u64 ism_get_local_gid(struct ism_dev *ism)
	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)
+10 −5
Original line number Diff line number Diff line
@@ -52,9 +52,14 @@ struct smcd_dmb {
struct smcd_dev;
struct ism_client;

struct smcd_gid {
	u64	gid;
	u64	gid_ext;
};

struct smcd_ops {
	int (*query_remote_gid)(struct smcd_dev *dev, u64 rgid, u32 vid_valid,
				u32 vid);
	int (*query_remote_gid)(struct smcd_dev *dev, struct smcd_gid *rgid,
				u32 vid_valid, u32 vid);
	int (*register_dmb)(struct smcd_dev *dev, struct smcd_dmb *dmb,
			    struct ism_client *client);
	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 (*set_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,
			    u32 event_code, u64 info);
	int (*signal_event)(struct smcd_dev *dev, struct smcd_gid *rgid,
			    u32 trigger_irq, u32 event_code, u64 info);
	int (*move_data)(struct smcd_dev *dev, u64 dmb_tok, unsigned int idx,
			 bool sf, unsigned int offset, void *data,
			 unsigned int size);
	int (*supports_v2)(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);
	struct device* (*get_dev)(struct smcd_dev *dev);
};
+53 −13
Original line number Diff line number Diff line
@@ -1044,7 +1044,8 @@ static int smc_find_ism_v2_device_clnt(struct smc_sock *smc,
{
	int rc = SMC_CLC_DECL_NOSMCDDEV;
	struct smcd_dev *smcd;
	int i = 1;
	int i = 1, entry = 1;
	bool is_virtual;
	u16 chid;

	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);
		if (!smc_find_ism_v2_is_unique_chid(chid, ini, i))
			continue;
		is_virtual = __smc_ism_is_virtual(chid);
		if (!smc_pnet_is_pnetid_set(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_chid[i] = chid;
			ini->is_smcd = true;
			rc = 0;
			i++;
			if (i > SMC_MAX_ISM_DEVS)
			entry = is_virtual ? entry + 2 : entry + 1;
			if (entry > SMCD_CLC_MAX_V2_GID_ENTRIES)
				break;
		}
	}
@@ -1402,8 +1412,13 @@ static int smc_connect_ism(struct smc_sock *smc,
		rc = smc_v2_determine_accepted_chid(aclc, ini);
		if (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 */
	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 */
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)
{
	struct smcd_dev *smcd;
@@ -2100,7 +2116,11 @@ static void smc_check_ism_v2_match(struct smc_init_info *ini,
			continue;
		if (smc_ism_get_chid(smcd) == proposed_chid &&
		    !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;
			(*matches)++;
			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_msg_smcd *pclc_smcd;
	unsigned int matches = 0;
	struct smcd_gid smcd_gid;
	u8 smcd_version;
	u8 *eid = NULL;
	int i, rc;
	u16 chid;

	if (!(ini->smcd_version & SMC_V2) || !smcd_indicated(ini->smc_type_v2))
		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);

	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 */
		smcd_gid.gid = ntohll(pclc_smcd->ism.gid);
		smcd_gid.gid_ext = 0;
		smc_check_ism_v2_match(ini, ntohs(pclc_smcd->ism.chid),
				       ntohll(pclc_smcd->ism.gid), &matches);
	for (i = 1; i <= smc_v2_ext->hdr.ism_gid_cnt; i++) {
				       &smcd_gid, &matches);
	}
	for (i = 0; i < smc_v2_ext->hdr.ism_gid_cnt; i++) {
		/* check for ISM devices matching proposed non-native ISM
		 * devices
		 */
		smc_check_ism_v2_match(ini,
				       ntohs(smcd_v2_ext->gidchid[i - 1].chid),
				       ntohll(smcd_v2_ext->gidchid[i - 1].gid),
				       &matches);
		smcd_gid.gid = ntohll(smcd_v2_ext->gidchid[i].gid);
		smcd_gid.gid_ext = 0;
		chid = ntohs(smcd_v2_ext->gidchid[i].chid);
		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);

@@ -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))
		goto not_found;
	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);
	if (rc)
		goto not_found;
+0 −3
Original line number Diff line number Diff line
@@ -29,9 +29,6 @@
#define SMCPROTO_SMC		0	/* SMC protocol, IPv4 */
#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 */

extern struct proto smc_proto;
+32 −11
Original line number Diff line number Diff line
@@ -892,11 +892,13 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
		       ETH_ALEN);
	}
	if (smcd_indicated(ini->smc_type_v1)) {
		struct smcd_gid smcd_gid;

		/* add SMC-D specifics */
		if (ini->ism_dev[0]) {
			smcd = ini->ism_dev[0];
			pclc_smcd->ism.gid =
				htonll(smcd->ops->get_local_gid(smcd));
			smcd->ops->get_local_gid(smcd, &smcd_gid);
			pclc_smcd->ism.gid = htonll(smcd_gid.gid);
			pclc_smcd->ism.chid =
				htons(smc_ism_get_chid(ini->ism_dev[0]));
		}
@@ -929,10 +931,11 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
		read_unlock(&smc_clc_eid_table.lock);
	}
	if (smcd_indicated(ini->smc_type_v2)) {
		struct smcd_gid smcd_gid;
		u8 *eid = NULL;
		int entry = 0;

		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) -
				offsetofend(struct smc_clnt_opts_area_hdr,
					    smcd_v2_ext_offset) +
@@ -944,14 +947,26 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
		if (ini->ism_offered_cnt) {
			for (i = 1; i <= ini->ism_offered_cnt; i++) {
				smcd = ini->ism_dev[i];
				gidchids[i - 1].gid =
					htonll(smcd->ops->get_local_gid(smcd));
				gidchids[i - 1].chid =
				smcd->ops->get_local_gid(smcd, &smcd_gid);
				gidchids[entry].chid =
					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 *
				sizeof(struct smc_clc_smcd_gid_chid);
				entry++;
			}
			plen += entry * sizeof(struct smc_clc_smcd_gid_chid);
		}
		v2_ext->hdr.ism_gid_cnt = entry;
	}
	if (smcr_indicated(ini->smc_type_v2)) {
		memcpy(v2_ext->roce, ini->smcrv2.ib_gid_v2, SMC_GID_SIZE);
@@ -987,7 +1002,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
			vec[i++].iov_len = sizeof(*smcd_v2_ext);
			if (ini->ism_offered_cnt) {
				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);
			}
		}
@@ -1018,13 +1033,16 @@ smcd_clc_prep_confirm_accept(struct smc_connection *conn,
			     struct smc_clc_msg_trail *trl)
{
	struct smcd_dev *smcd = conn->lgr->smcd;
	struct smcd_gid smcd_gid;
	u16 chid;
	int len;

	/* SMC-D specific settings */
	memcpy(clc->hdr.eyecatcher, SMCD_EYECATCHER,
	       sizeof(SMCD_EYECATCHER));
	smcd->ops->get_local_gid(smcd, &smcd_gid);
	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.dmbe_size = conn->rmbe_size_comp;
	clc->d0.dmbe_idx = 0;
@@ -1032,9 +1050,12 @@ smcd_clc_prep_confirm_accept(struct smc_connection *conn,
	if (version == SMC_V1) {
		clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN);
	} 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])
			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;
		if (first_contact) {
			*fce_len = smc_clc_fill_fce_v2x(fce_v2x, ini);
Loading